home *** CD-ROM | disk | FTP | other *** search
/ Quick PC 61 / Quick PC 61.iso / I386 / SQLRUN.CAB / sp3Repl.sql.185C1D8F_1545_4277_BB64_857D2622DB57 < prev    next >
Encoding:
Text File  |  2002-12-04  |  544.8 KB  |  17,026 lines

  1. use master
  2. go
  3.  
  4. dump tran master with no_log
  5. go
  6.  
  7. exec dbo.sp_configure 'allow updates',1
  8. go
  9. reconfigure with override
  10. go
  11.  
  12. set ANSI_NULLS off
  13.  
  14. exec sp_MS_upd_sysobj_category 1
  15. go
  16.  
  17. --------------------------------------------------------------------------------
  18. --.    System objects (replsys.sql)
  19. --------------------------------------------------------------------------------
  20. --------------------------------------------------------------------------------
  21. --. sp_MSispulldistributionjobnamegenerated
  22. --------------------------------------------------------------------------------
  23. if exists (select * from sysobjects
  24.     where type = 'P' and name = 'sp_MSispulldistributionjobnamegenerated')
  25. drop procedure sp_MSispulldistributionjobnamegenerated
  26. go
  27.  
  28. raiserror('Creating procedure sp_MSispulldistributionjobnamegenerated', 0,1) with nowait
  29. go
  30. --
  31. -- Name: sp_MSispulldistributionjobnamegenerated
  32. --
  33. -- Descriptions: This procedure checks whether a given job id corresponds to
  34. --               a pull distribution agent job with a name generated by replication. 
  35. --               If so, a return value of zero will be returned, otherwise
  36. --               a value of one will be returned to the caller.
  37. -- 
  38. -- Notes: 1) For this procedure to be effective, it must match the current
  39. --           pull distribution agent name generation algorithm. Note that the 
  40. --           algorithm used for matching auto-generated job name is not 
  41. --           exact. (See sp_addpullsubscription_agent replsys.sql)
  42. --        2) This procedure is supposed to be executed at the subscriber
  43. --           database. The subscriber server name and subscriber database
  44. --           name for contructing the generated job name are obtained via
  45. --           the serverproperty('ServerName') and the db_name() functions. 
  46. --
  47. -- Parameters: @publisher     sysname
  48. --             @publisher_db  sysname
  49. --             @publication   sysname (This can be null for shared agent)
  50. --             @job_id        uniqueidentifier
  51. --
  52. -- Returns: 0 - If the specified jobid corresponds to a snapshot job with
  53. --              a generated name.
  54. --          1 - Otherwise
  55. --
  56. -- Security: This is an internal system procedure.
  57. --
  58. create procedure dbo.sp_MSispulldistributionjobnamegenerated (
  59.     @publisher     sysname,
  60.     @publisher_db  sysname,
  61.     @publication   sysname,
  62.     @job_id        uniqueidentifier
  63.     )
  64. as
  65. begin
  66.     set nocount on
  67.  
  68.     declare @generated_job_name nvarchar(4000)
  69.     declare @generated_job_name_length int
  70.     declare @job_name sysname
  71.  
  72.     select @job_name = null
  73.     select @job_name = name
  74.       from msdb.dbo.sysjobs_view 
  75.      where job_id = @job_id
  76.  
  77.     if @job_name is null
  78.     begin
  79.         goto MISMATCH
  80.     end
  81.  
  82.     -- First of all, make sure that the job is indeed a distribution agent
  83.     -- job (there should be a step with Distribution as the subsystem in the 
  84.     -- job)
  85.     if not exists (select * 
  86.                      from msdb.dbo.sysjobsteps
  87.                     where job_id = @job_id
  88.                       and upper(subsystem collate SQL_Latin1_General_CP1_CS_AS) = N'DISTRIBUTION')
  89.     begin
  90.         goto MISMATCH
  91.     end
  92.                     
  93.     -- Pull distribution agent names are always generated with a guid
  94.     select @generated_job_name = left(@publisher, 21) + N'-'
  95.                                + left(@publisher_db, 21) + N'-'
  96.                                + left(@publication, 21) + N'-'
  97.                                + left(convert(nvarchar(4000),serverproperty('ServerName')), 21) + N'-'
  98.                                + left(db_name(), 21) + N'-'
  99.  
  100.     select @generated_job_name_length = len(@generated_job_name)
  101.  
  102.     -- Try matching the prefix of the job name
  103.     if left(@job_name, @generated_job_name_length) = @generated_job_name
  104.     begin
  105.         -- Checks if the tail end of the job name matches a hexadecimal guid 
  106.         -- with embedded dashes
  107.         if upper(right(@job_name, len(@job_name) - @generated_job_name_length) collate SQL_Latin1_General_CP1_CS_AS)
  108.             like N'[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]'
  109.         begin
  110.             return 0
  111.         end
  112.         else
  113.         begin
  114.             goto MISMATCH
  115.         end
  116.     end
  117.  
  118. MISMATCH:
  119.     if @job_name is not null
  120.     begin
  121.         raiserror(21695, -1, -1, @job_name)
  122.     end
  123.     return 1
  124. end
  125. go
  126. exec sp_MS_marksystemobject 'dbo.sp_MSispulldistributionjobnamegenerated'
  127.  
  128. --------------------------------------------------------------------------------
  129. --. sp_MSispullmergejobnmaegenerated
  130. --------------------------------------------------------------------------------
  131. if exists (select * from sysobjects
  132.     where type = 'P' and name = 'sp_MSispullmergejobnamegenerated')
  133. drop procedure sp_MSispullmergejobnamegenerated
  134. go
  135.  
  136. raiserror('Creating procedure sp_MSispullmergejobnamegenerated', 0,1) with nowait
  137. go
  138. --
  139. -- Name: sp_MSispullmergejobnamegenerated
  140. --
  141. -- Descriptions: This procedure checks whether a given job id corresponds to
  142. --               a pull merge agent job with a name generated by replication. 
  143. --               If so, a return value of zero will be returned, otherwise
  144. --               a value of one will be returned to the caller.
  145. -- 
  146. -- Notes: 1) For this procedure to be effective, it must match the current
  147. --           pull merge agent name generation algorithm. Note that the 
  148. --           algorithm used for matching auto-generated job name is not 
  149. --           exact. (See sp_addmergepullsubscription_agent replsys.sql)
  150. --        2) This procedure is supposed to be executed at the subscriber
  151. --           database. The subscriber server name and subscriber database
  152. --           name for contructing the generated job name are obtained via
  153. --           the serverproperty('ServerName') and the db_name() functions. 
  154. --
  155. -- Parameters: @publisher     sysname
  156. --             @publisher_db  sysname
  157. --             @publication   sysname (This can be null for shared agent)
  158. --             @job_id        uniqueidentifier
  159. --
  160. -- Returns: 0 - If the specified jobid corresponds to a snapshot job with
  161. --              a generated name.
  162. --          1 - Otherwise
  163. --
  164. -- Security: This is an internal system procedure.
  165. --
  166. create procedure dbo.sp_MSispullmergejobnamegenerated (
  167.     @publisher    sysname,
  168.     @publisher_db sysname,
  169.     @publication  sysname,
  170.     @job_id       uniqueidentifier
  171.     )
  172. as
  173. begin
  174.     set nocount on
  175.     
  176.     declare @generated_job_name nvarchar(4000)
  177.     declare @generated_job_name_length int
  178.     declare @job_name sysname
  179.  
  180.     select @job_name = null
  181.     select @job_name = name
  182.       from msdb.dbo.sysjobs_view
  183.      where job_id = @job_id
  184.  
  185.     if @job_name = null
  186.     begin
  187.         goto MISMATCH
  188.     end
  189.     
  190.     -- First of all, make sure that the given job is indeed a merge agent
  191.     -- job (There should be a step with Distribution as the subsystem in the 
  192.     -- job)
  193.     if not exists (select * 
  194.                      from msdb.dbo.sysjobsteps
  195.                     where job_id = @job_id
  196.                       and upper(subsystem collate SQL_Latin1_General_CP1_CS_AS) = N'MERGE')
  197.     begin
  198.         goto MISMATCH
  199.     end
  200.     
  201.     -- Pull merge agent names are always generated with a - 0 extension
  202.     select @generated_job_name = left(@publisher, 23) + N'-'
  203.                                + left(@publisher_db, 23) + N'-'
  204.                                + left(@publication, 23) + N'-'
  205.                                + left(convert(nvarchar(4000),serverproperty('ServerName')), 23) + N'-'
  206.                                + left(db_name(), 23) + N'- 0'
  207.  
  208.     if @job_name = @generated_job_name
  209.     begin
  210.         return 0
  211.     end    
  212.  
  213. MISMATCH:
  214.     if @job_name is not null
  215.     begin
  216.         raiserror(21695, -1, -1, @job_name)
  217.     end
  218.     return 1
  219. end
  220. go
  221. exec sp_MS_marksystemobject 'dbo.sp_MSispullmergejobnamegenerated'
  222.  
  223. --------------------------------------------------------------------------------
  224. --. sp_droppullsubscription
  225. --------------------------------------------------------------------------------
  226. if exists (select * from sysobjects
  227.     where type = 'P' and name = 'sp_droppullsubscription')
  228. drop procedure sp_droppullsubscription
  229. go
  230.  
  231. raiserror('Creating procedure sp_droppullsubscription', 0,1)
  232. go
  233.  
  234. CREATE PROCEDURE sp_droppullsubscription (
  235.     @publisher sysname,
  236.     @publisher_db sysname,
  237.     @publication sysname,   /* publication name */
  238.     @reserved bit = 0
  239.     ) AS
  240.  
  241.     SET NOCOUNT ON
  242.  
  243.     /*
  244.     ** Declarations.
  245.     */
  246.  
  247.  
  248.     DECLARE @name nvarchar(255)
  249.     DECLARE @retcode int
  250.     DECLARE @agent_id binary(16)
  251.     DECLARE @publisher_ex sysname          /* Expression used in the cursor */
  252.     DECLARE @publisher_db_ex sysname     /* Expression used in the cursor */
  253.     DECLARE @publication_ex sysname      /* Expression used in the cursor */
  254.     DECLARE @expanded bit
  255.     DECLARE @subscription_type_id int
  256.     DECLARE @count_sub int
  257.     DECLARE @drop_null_pub bit
  258.     DECLARE @drop_push_bit bit
  259.     DECLARE @push int
  260.     DECLARE @implicit_transaction int
  261.     DECLARE @close_cursor_at_commit int
  262.     DECLARE @owner_sid varbinary(85)
  263.     DECLARE @owner_name sysname
  264.     DECLARE @qualified_publication_name nvarchar(512)
  265.     
  266.     /* 
  267.     ** Initialization
  268.     */
  269.     SELECT @expanded = 0
  270.     SELECT @drop_null_pub = 0
  271.     SELECT @push = 0
  272.  
  273.     /*
  274.     ** Get the original set value off IMPLICIT_TRANSACTIONS and CURSOR_CLOSE_ON_COMMIT
  275.     **      before set these two to off
  276.     */
  277.     select @implicit_transaction = 0
  278.     select @close_cursor_at_commit = 0
  279.     IF (@reserved = 0)
  280.     BEGIN
  281.         SELECT @implicit_transaction = @@options & 2
  282.         SELECT @close_cursor_at_commit = @@options & 4
  283.         SET IMPLICIT_TRANSACTIONS OFF
  284.         SET CURSOR_CLOSE_ON_COMMIT OFF
  285.     END
  286.  
  287.     /*
  288.     ** Security Check
  289.     */
  290.  
  291.     EXEC @retcode = dbo.sp_MSreplcheck_subscribe
  292.     IF @@ERROR <> 0 or @retcode <> 0
  293.         RETURN(1)
  294.  
  295.     SELECT @drop_push_bit = 0   
  296.     
  297.     /*
  298.     ** Check parameter and set expressions used by cursor
  299.     */
  300.     
  301.     /* Publisher */
  302.     IF @publisher IS NULL
  303.     BEGIN
  304.         RAISERROR (14043, 16, -1, '@publisher')
  305.         RETURN (1)
  306.     END
  307.  
  308.     IF @publisher = 'all'
  309.     BEGIN
  310.         SELECT @publisher_ex = '%'
  311.         SELECT @expanded = 1
  312.     END
  313.     ELSE
  314.     BEGIN
  315.         EXECUTE @retcode = dbo.sp_validname @publisher
  316.         IF @retcode <> 0
  317.         RETURN (1)
  318.         SELECT @publisher_ex = @publisher
  319.     END
  320.  
  321.  
  322.     /* Publisher_db */
  323.     IF @publisher_db IS NULL
  324.     BEGIN
  325.             RAISERROR (14043, 16, -1, '@publisher_db')
  326.             RETURN (1)
  327.     END
  328.  
  329.     IF @publisher_db = 'all'
  330.     BEGIN
  331.         SELECT @publisher_db_ex = '%'
  332.         select @expanded = 1
  333.     END
  334.     ELSE
  335.     BEGIN
  336.         /*
  337.         EXECUTE @retcode = dbo.sp_validname @publisher_db
  338.         IF @retcode <> 0
  339.         RETURN (1)
  340.         */
  341.         SELECT @publisher_db_ex = @publisher_db
  342.     END
  343.  
  344.     /* 
  345.     ** Publication
  346.     ** '' is not a valid name but it may be in the publication name in the table. 
  347.     */
  348.     IF @publication IS NULL OR @publication = ''
  349.     BEGIN
  350.         SELECT @drop_null_pub = 1
  351.     END
  352.     ELSE IF @publication = 'all'
  353.     BEGIN
  354.         SELECT @publication_ex = '%'
  355.         SELECT @expanded = 1
  356.         SELECT @drop_null_pub = 1
  357.     END
  358.     ELSE
  359.     BEGIN
  360.         EXECUTE @retcode = dbo.sp_validname @publication
  361.         IF @retcode <> 0
  362.         RETURN (1)
  363.         SELECT @publication_ex = @publication
  364.     END
  365.  
  366.     /*
  367.     ** Check to see if the  subscription table exists
  368.     */
  369.     IF NOT EXISTS (SELECT * FROM sysobjects 
  370.                 WHERE type = 'U' AND
  371.                       name = 'MSreplication_subscriptions')
  372.     BEGIN
  373.         IF @expanded = 0
  374.         BEGIN
  375.             RAISERROR(14135, 11, -1,  @publisher, 
  376.                 @publisher_db, @publication)
  377.             RETURN(1)
  378.         END
  379.         ELSE
  380.             RETURN(0)
  381.     END
  382.  
  383.     IF @expanded = 0 
  384.     BEGIN 
  385.         /*
  386.         **
  387.         ** Check to see if the subscription entry exists
  388.         */
  389.         IF  NOT EXISTS (SELECT * FROM  MSreplication_subscriptions 
  390.                     WHERE UPPER(publisher) = UPPER(@publisher) AND
  391.                       publisher_db = @publisher_db AND
  392.                       publication = @publication)     
  393.         BEGIN
  394.             RAISERROR(14135, 11, -1, @publisher, @publisher_db, @publication)
  395.             RETURN(1)
  396.         END
  397.  
  398.         /* 
  399.         ** Make sure the subscription is not push type if @drop_push_bit = 0
  400.         */
  401.         IF @drop_push_bit = 0
  402.         BEGIN
  403.             IF EXISTS (SELECT * FROM MSreplication_subscriptions 
  404.                 WHERE UPPER(publisher) = UPPER(@publisher) AND
  405.                   publisher_db = @publisher_db AND
  406.                   publication = @publication AND
  407.                   subscription_type = @push AND
  408.                   @drop_push_bit = 0)
  409.             BEGIN
  410.                 RAISERROR(20017, 16, -1)
  411.                 RETURN(1)
  412.             END
  413.         END
  414.  
  415.     END
  416.     ELSE
  417.     /* 
  418.     ** Open a cursor and call recursively if
  419.     ** parameters are expanded.
  420.     */
  421.     BEGIN
  422.  
  423.         /*      
  424.         **  Note: Any expression check on null value is false
  425.         ** @subscription_type_id is NULL <==> push
  426.         ** @subscription_type_id is NOT NULL <==> non push
  427.         */
  428.         -- Have to use static cursor option because 
  429.         DECLARE hCdroppullsubscription CURSOR STATIC LOCAL FORWARD_ONLY FOR
  430.             SELECT DISTINCT publisher, publisher_db, publication    
  431.                 FROM MSreplication_subscriptions
  432.                 WHERE ((@publisher_ex = N'%') OR (UPPER(publisher) = UPPER(@publisher_ex))) AND
  433.                                           ((@publisher_db_ex = N'%') OR ( publisher_db = @publisher_db_ex)) AND
  434.                       (publication LIKE @publication_ex OR
  435.                       (@drop_null_pub = 1 AND
  436.                       publication IS NULL)) AND
  437.                       ((@drop_push_bit =0 AND
  438.                       subscription_type <> @push) OR
  439.                       @drop_push_bit = 1)
  440.         FOR READ ONLY
  441.         OPEN hCdroppullsubscription
  442.  
  443.         FETCH hCdroppullsubscription INTO @publisher, 
  444.             @publisher_db, @publication
  445.         WHILE (@@fetch_status <> -1)
  446.         BEGIN
  447.             EXECUTE @retcode  = dbo.sp_droppullsubscription @publisher = @publisher, 
  448.                 @publisher_db = @publisher_db, @publication = @publication, 
  449.                 @reserved = 1
  450.  
  451.             FETCH hCdroppullsubscription INTO @publisher, 
  452.                 @publisher_db, @publication
  453.         END
  454.  
  455.         CLOSE hCdroppullsubscription
  456.         DEALLOCATE hCdroppullsubscription
  457.         RETURN (0)
  458.     END
  459.     
  460.     /*
  461.     ** Only members of the sysadmin group and the creator of the distribution
  462.     ** agent can drop a pull subscription successfully. This behavior matches 
  463.     ** the behavior of the sysjobs_view. DBO of the subscriber database, 
  464.     ** sysadmins (owner is undefined) can drop a subscription if the owner_sid 
  465.     ** is null.
  466.     */
  467.  
  468.     EXEC sp_MSget_pullsubsagent_owner @publisher = @publisher,
  469.                                       @publisher_db = @publisher_db,
  470.                                       @publication = @publication,
  471.                                       @owner_sid = @owner_sid OUTPUT
  472.  
  473.     IF (@owner_sid is not null AND
  474.         (SUSER_SID() <> @owner_sid) AND
  475.         (ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0))
  476.     BEGIN
  477.         SELECT @owner_name = SUSER_SNAME(@owner_sid)
  478.         SELECT @qualified_publication_name = @publisher + N':' + 
  479.                                              @publisher_db + N':' +
  480.                                              @publication
  481.         RAISERROR(21121,16,-1,@owner_name, @qualified_publication_name) 
  482.         RETURN (1)
  483.     END
  484.  
  485.     /* 
  486.     ** Get the agent name, it may be dropped later.
  487.     */
  488.     SELECT @agent_id = agent_id FROM MSreplication_subscriptions
  489.                     WHERE UPPER(publisher) = UPPER(@publisher) AND
  490.                           publisher_db  = @publisher_db AND
  491.                           publication = @publication 
  492.  
  493.     -- If the agent is used by other subscription, don't drop it.
  494.     if (select count(*) from MSreplication_subscriptions where
  495.         agent_id = @agent_id) > 1
  496.         select @agent_id = NULL
  497.  
  498.     begin tran
  499.     save TRAN droppullsubscription
  500.  
  501.     /*
  502.     ** Drop the subscription entry and the distribution agent if it exists 
  503.     */
  504.  
  505.  
  506.     /* 
  507.     ** If the distribution agent is not used anymore,
  508.     ** drop the agent if it exists
  509.     */
  510.  
  511.     IF @agent_id IS NOT NULL
  512.     BEGIN
  513.         IF (EXISTS (SELECT * FROM msdb..sysjobs_view WHERE job_id = @agent_id))
  514.         BEGIN
  515.             -- Checks if the job name matches one that is generated
  516.             -- by replication
  517.             EXEC @retcode = dbo.sp_MSispulldistributionjobnamegenerated
  518.                                @publisher = @publisher,
  519.                                @publisher_db = @publisher_db,
  520.                                @publication = @publication,
  521.                                @job_id = @agent_id
  522.             IF @@ERROR <> 0
  523.                 GOTO UNDO
  524.  
  525.             -- Only drop jobs if the name was generated
  526.             IF @retcode = 0
  527.             BEGIN
  528.                 EXEC @retcode = msdb.dbo.sp_delete_job @job_id = @agent_id
  529.                 IF @@ERROR <> 0 or @retcode <> 0
  530.                     GOTO UNDO
  531.  
  532.                 -- Delete MSreplication_subsciptions table after dropping 
  533.                 -- the distribution agent and delay one second
  534.                 -- to avoid deadlock with it.
  535.                 WAITFOR DELAY '00:00:01'
  536.             END
  537.         END
  538.  
  539.     END
  540.  
  541.     /* Call sp_MSunregistersubscription so that the reg entries get deleted */
  542.     declare @subscriber_db sysname
  543.     set @subscriber_db = DB_NAME()
  544.     exec @retcode = dbo.sp_MSunregistersubscription @publisher = @publisher,
  545.                                 @publisher_db = @publisher_db,
  546.                                 @publication = @publication,
  547.                                 @subscriber = @@SERVERNAME,
  548.                                 @subscriber_db = @subscriber_db
  549.  
  550.     IF @retcode<>0 or @@ERROR<>0
  551.         GOTO UNDO
  552.     /*
  553.     -- Delete MSreplication_subsciptions table after dropping the distribution agent\
  554.     -- To avoid deadlock with it.
  555.     --DELETE MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND
  556.         --publisher_db  = @publisher_db AND
  557.         --publication = @publication 
  558.     
  559.     --IF @@ERROR <> 0 
  560.     --  GOTO UNDO
  561.  
  562.     */
  563.     
  564.     IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties')
  565.     BEGIN
  566.         DELETE FROM MSsubscription_properties 
  567.         WHERE UPPER(publisher) = UPPER(@publisher)  AND
  568.         publisher_db  = @publisher_db AND
  569.         publication = @publication 
  570.  
  571.         IF @@ERROR <> 0 
  572.             GOTO UNDO
  573.  
  574.         IF NOT EXISTS (SELECT * FROM MSsubscription_properties)
  575.         BEGIN
  576.             exec @retcode = dbo.sp_MSsub_cleanup_prop_table
  577.             IF @@ERROR <> 0 or @retcode <> 0
  578.                 GOTO UNDO
  579.         END
  580.     END
  581.     
  582.     /*
  583.     ** Clean up metadata at subscriber side
  584.     */
  585.     -- Note: sp_subscription_cleanup should be called after deleting the row
  586.     -- in MSreplication_subscriptions.
  587.     exec @retcode = dbo.sp_subscription_cleanup @publisher = @publisher,
  588.                                             @publisher_db  = @publisher_db,
  589.                                             @publication = @publication
  590.     IF @retcode<>0 or @@ERROR<>0
  591.         GOTO UNDO
  592.  
  593.     --
  594.     -- drop table MSreplication_subscriptions if empty and
  595.     -- not in recursive call
  596.     --
  597.     IF EXISTS (SELECT * 
  598.                  FROM sysobjects 
  599.                 WHERE name = 'MSreplication_subscriptions' 
  600.                   AND type = 'U')
  601.     BEGIN
  602.         IF (@reserved = 0 AND 
  603.             NOT EXISTS (SELECT * FROM MSreplication_subscriptions))
  604.         BEGIN
  605.             DROP TABLE MSreplication_subscriptions
  606.             IF @@ERROR <> 0 
  607.                 GOTO UNDO
  608.         END
  609.     END
  610.  
  611.     COMMIT TRAN
  612.     /*
  613.     ** set back the two settings if needed 
  614.     */
  615.     if @reserved = 0
  616.     BEGIN
  617.         IF @implicit_transaction <>0 
  618.             SET IMPLICIT_TRANSACTIONS ON
  619.         IF @close_cursor_at_commit <>0 
  620.             SET CURSOR_CLOSE_ON_COMMIT ON
  621.     END
  622.     RETURN (0)
  623.  
  624. UNDO:
  625.     IF @@TRANCOUNT > 0
  626.     begin
  627.         ROLLBACK TRAN droppullsubscription
  628.         COMMIT TRAN   
  629.     end
  630.     /*
  631.     ** set back the two settings if needed
  632.     */
  633.     if @reserved = 0
  634.     BEGIN
  635.         IF @implicit_transaction <>0 
  636.             SET IMPLICIT_TRANSACTIONS ON
  637.         IF @close_cursor_at_commit <>0 
  638.             SET CURSOR_CLOSE_ON_COMMIT ON
  639.     END
  640.  
  641.     return 1
  642. go
  643. exec sp_MS_marksystemobject 'dbo.sp_droppullsubscription'
  644. grant execute on dbo.sp_droppullsubscription to public
  645. --------------------------------------------------------------------------------
  646. --. sp_dropmergepullsubscription
  647. --------------------------------------------------------------------------------
  648. if exists (select * from sysobjects
  649.     where type = 'P' and name = 'sp_dropmergepullsubscription')
  650. drop procedure sp_dropmergepullsubscription
  651. go
  652. raiserror('Creating procedure sp_dropmergepullsubscription', 0,1)
  653. GO
  654. CREATE PROCEDURE sp_dropmergepullsubscription(
  655.     @publication        sysname = NULL,             /* Publication name */
  656.     @publisher          sysname = NULL,             /* Publisher server */
  657.     @publisher_db       sysname = NULL,             /* Publication database */
  658.     @reserved           bit = 0
  659.     )AS
  660.  
  661.     SET NOCOUNT ON
  662.  
  663.     /*
  664.     ** Declarations.
  665.     */
  666.  
  667.     declare @retcode                int
  668.     declare @subscriber_srvid       int
  669.     declare @publisher_srvid        int
  670.     declare @pubid                  uniqueidentifier
  671.     declare @subid                  uniqueidentifier
  672.     declare @partnerid              uniqueidentifier 
  673.     declare @local_server           sysname
  674.     declare @local_db               sysname
  675.     declare @merge_jobid            binary(16)
  676.     declare @cmd                    nvarchar(255)
  677.     declare @pubidstr               nvarchar(38)
  678.     declare @subscriber             sysname
  679.     declare @subscriber_db          sysname
  680.     declare @subscriber_type        int
  681.     declare @local_job              bit
  682.     declare @implicit_transaction   int
  683.     declare @close_cursor_at_commit int
  684.     declare @owner_sid              varbinary(85)
  685.     declare @owner_name             sysname
  686.     declare @qualified_publication_name nvarchar(512)
  687.  
  688.  
  689.     select @close_cursor_at_commit = 0
  690.     select @implicit_transaction = 0
  691.  
  692.     /*
  693.     ** Get original setting values before setting them to false for recursive calling
  694.     */
  695.     IF (@reserved = 0)
  696.     BEGIN
  697.         SELECT @implicit_transaction = @@options & 2
  698.         SELECT @close_cursor_at_commit = @@options & 4
  699.         SET IMPLICIT_TRANSACTIONS OFF
  700.         SET CURSOR_CLOSE_ON_COMMIT OFF
  701.     END
  702.  
  703.     /* 
  704.     ** Security Check.
  705.     */
  706.     exec @retcode = dbo.sp_MSreplcheck_subscribe
  707.     if @@ERROR <> 0 or @retcode <> 0
  708.         return(1)
  709.  
  710.      /*
  711.     ** Initializations.
  712.     */              
  713.     set @local_db = DB_NAME()
  714.     set @local_server = @@SERVERNAME
  715.     set @subscriber = @@SERVERNAME   
  716.     set @subscriber_db = DB_NAME()
  717.  
  718.    /*
  719.     ** Assign parameter values appropriately
  720.     */
  721.             
  722.     select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  723.     IF @subscriber_srvid IS NULL
  724.         BEGIN
  725.            RAISERROR (14010, 16, -1)
  726.            RETURN (1)     
  727.         END
  728.         
  729.     IF not exists (select name from sysobjects where name='sysmergesubscriptions')
  730.         BEGIN
  731.             RAISERROR (14055, 16, -1)
  732.             RETURN (1)
  733.         END     
  734.  
  735.     /*
  736.     ** Parameter Check: @publisher
  737.     ** Check to make sure that the publisher is defined
  738.     */
  739.             IF @publisher IS NULL
  740.             BEGIN
  741.                 RAISERROR (14043, 16, -1, '@publisher')
  742.                 RETURN (1)
  743.             END
  744.  
  745.             EXECUTE @retcode = dbo.sp_validname @publisher
  746.             IF @@ERROR <> 0 OR @retcode <> 0
  747.                RETURN (1)
  748.  
  749.     /*
  750.     ** Parameter Check: @publisher_db
  751.     */
  752.             IF @publisher_db IS NULL
  753.             BEGIN
  754.                 RAISERROR (14043, 16, -1, '@publisher_db')
  755.                 RETURN (1)
  756.             END    
  757.  
  758.     /*
  759.     ** Parameter Check:  @publication.
  760.     ** If the publication name is specified, check to make sure that it
  761.     ** conforms to the rules for identifiers and that the publication
  762.     ** actually exists.  Disallow NULL.
  763.     */
  764.     if @publication IS NULL
  765.         BEGIN
  766.             RAISERROR (14043, 16, -1, '@publication')
  767.             RETURN (1)
  768.         END
  769.  
  770.     IF LOWER(@publication) = 'all'
  771.         BEGIN
  772.             declare hC1 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name FROM sysmergepublications FOR READ ONLY
  773.             
  774.             OPEN hC1
  775.             FETCH hC1 INTO @publication
  776.             if @@fetch_status = -1 
  777.                 begin
  778.                     CLOSE hC1
  779.                     DEALLOCATE hC1
  780.                     RETURN (0) --- It's OK to have no publication when 'ALL'
  781.                 end
  782.             WHILE (@@fetch_status <> -1)
  783.                 BEGIN
  784.                     EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication,
  785.                                       @publisher = @publisher,
  786.                                       @publisher_db = @publisher_db,
  787.                                       @reserved = 1
  788.                     FETCH hC1 INTO @publication
  789.                 END
  790.             CLOSE hC1
  791.             DEALLOCATE hC1
  792.             RETURN (0)
  793.         END
  794.         
  795.     IF LOWER(@publisher) = 'all'
  796.         BEGIN
  797.             declare hC4 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT srvname FROM master..sysservers FOR READ ONLY
  798.             
  799.             OPEN hC4
  800.             FETCH hC4 INTO @publisher
  801.             WHILE (@@fetch_status <> -1)
  802.                 BEGIN
  803.                     EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication,
  804.                                                 @publisher = @publisher,
  805.                                                 @publisher_db = @publisher_db,
  806.                                                 @reserved = 1
  807.                     FETCH hC4 INTO @publisher
  808.                 END
  809.             CLOSE hC4
  810.             DEALLOCATE hC4
  811.             RETURN (0)
  812.         END
  813.  
  814.     /*
  815.     ** Validate that the publisher is a valid server
  816.     */
  817.     select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  818.     IF @publisher_srvid IS NULL
  819.         BEGIN
  820.             --RAISERROR (14010, 16, -1)
  821.             RETURN (1)
  822.         END
  823.  
  824.  
  825.     /* Previously the condition is set as 'AND subid<>pubid' which is fatally errorous */
  826.  
  827.     IF LOWER(@publisher_db) = 'all'
  828.         BEGIN
  829.             declare hC5 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT db_name FROM sysmergesubscriptions 
  830.                     WHERE subid = pubid and pubid in (select pubid from sysmergepublications 
  831.                             where UPPER(publisher)=UPPER(@publisher) 
  832.                                 and name=@publication)
  833.                                 
  834.                         FOR READ ONLY
  835.             
  836.             OPEN hC5
  837.             FETCH hC5 INTO @publisher_db
  838.             WHILE (@@fetch_status <> -1)
  839.                 BEGIN
  840.                     EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication,
  841.                                       @publisher = @publisher,
  842.                                       @publisher_db = @publisher_db,
  843.                                       @reserved = 1
  844.                     FETCH hC5 INTO @publisher_db
  845.                 END
  846.             CLOSE hC5
  847.             DEALLOCATE hC5
  848.             RETURN (0)
  849.         END
  850.  
  851.     /*
  852.     ** return error if only there is no 'ALL'. Same is true for the rest of error handling.
  853.     */
  854.     if NOT EXISTS (select * FROM sysmergepublications 
  855.     WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db) 
  856.     BEGIN
  857.         if @reserved = 0
  858.             RAISERROR (20026, 16, -1, @publication)
  859.         RETURN (1)
  860.     END
  861.         
  862.     select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  863.     set @pubidstr = '''' + convert(nchar(36), @pubid) + ''''
  864.     if @pubid is null  
  865.         BEGIN
  866.             if @reserved = 0
  867.                 RAISERROR (20026, 16, -1, @publication)
  868.             RETURN (1)
  869.         END
  870.  
  871.     /*
  872.     ** Only members of the sysadmin group and the creator of the distribution
  873.     ** agent can drop a pull subscription successfully. This behavior matches 
  874.     ** the behavior of the sysjobs_view. DBO of the subscriber database, 
  875.     ** sysadmins (owner is undefined) can drop a subscription if the owner_sid 
  876.     ** is null.
  877.     */
  878.     
  879.     EXEC sp_MSget_mergepullsubsagent_owner @publisher = @publisher,
  880.                                            @publisher_db = @publisher_db,
  881.                                            @publication = @publication,
  882.                                            @owner_sid = @owner_sid OUTPUT 
  883.     
  884.     IF (@owner_sid is not null AND
  885.         (SUSER_SID() <> @owner_sid) AND
  886.         (ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0))
  887.     BEGIN
  888.         SELECT @owner_name = SUSER_SNAME(@owner_sid)
  889.         SELECT @qualified_publication_name = @publisher + N':' + 
  890.                                              @publisher_db + N':' +
  891.                                              @publication
  892.         RAISERROR(21121,16,-1,@owner_name, @qualified_publication_name) 
  893.         RETURN (1)
  894.     END
  895.  
  896.     /*
  897.     ** Get subscriptions from either local replicas or global replicas
  898.     */
  899.     select @subid = subs1.subid, @subscriber_type = subs1.subscriber_type, @partnerid = subs2.subid from
  900.         sysmergesubscriptions   subs1,
  901.         sysmergesubscriptions   subs2,
  902.         sysmergepublications        pubs
  903.         where subs1.srvid = @subscriber_srvid
  904.             and subs1.db_name = @subscriber_db
  905.             and subs2.srvid = @publisher_srvid
  906.             and subs2.db_name = @publisher_db
  907.             and subs1.pubid = subs2.subid
  908.             and subs2.pubid = pubs.pubid
  909.             and pubs.name = @publication
  910.             and UPPER(pubs.publisher)=UPPER(@publisher)
  911.             and pubs.publisher_db=@publisher_db
  912.  
  913.     if @subid IS NULL 
  914.         begin
  915.             if @reserved = 0 
  916.                 raiserror (14050, 16, -1)
  917.             RETURN (0)
  918.         end                 
  919.  
  920.     begin tran
  921.     save TRAN dropmergepullsubscription
  922.     
  923.         /*  
  924.         ** Drop the local merge task
  925.         */
  926.         select @merge_jobid = merge_jobid from MSmerge_replinfo WHERE repid = @subid
  927.         if (@merge_jobid IS NOT NULL)
  928.         BEGIN
  929.             IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE job_id = @merge_jobid)
  930.             BEGIN
  931.  
  932.                 -- Checks if the job name matches one that is generated
  933.                 -- by replication
  934.                 EXEC @retcode = dbo.sp_MSispullmergejobnamegenerated
  935.                                     @publisher = @publisher,
  936.                                     @publisher_db = @publisher_db,
  937.                                     @publication = @publication,
  938.                                     @job_id = @merge_jobid
  939.                 IF @@ERROR <> 0
  940.                     GOTO FAILURE
  941.  
  942.                 -- Only drop the job if the name was generated
  943.                 IF @retcode = 0
  944.                 BEGIN
  945.                     EXEC @retcode = msdb.dbo.sp_delete_job @job_id = @merge_jobid
  946.                     IF @@ERROR <> 0 or @retcode <> 0
  947.                         GOTO FAILURE
  948.                 END
  949.             END
  950.         END                                 
  951.  
  952.         if @subid <> @partnerid
  953.         BEGIN
  954.             DELETE MSmerge_replinfo WHERE repid = @subid 
  955.             IF @@ERROR <> 0
  956.                 GOTO FAILURE
  957.             delete from sysmergesubscriptions where subid = @subid
  958.             if @@ERROR <> 0
  959.                 GOTO FAILURE
  960.  
  961.             /* Call sp_MSunregistersubscription so that the reg entries get deleted */
  962.             exec @retcode = dbo.sp_MSunregistersubscription @publisher = @publisher,
  963.                                         @publisher_db = @publisher_db,
  964.                                         @publication = @publication,
  965.                                         @subscriber = @@SERVERNAME,
  966.                                         @subscriber_db = @subscriber_db
  967.             IF @retcode<>0 or @@ERROR<>0
  968.                 GOTO FAILURE
  969.  
  970.             exec dbo.sp_MSpublicationcleanup @publisher=@publisher, 
  971.                                             @publisher_db = @publisher_db,
  972.                                             @publication = @publication
  973.             IF @@ERROR <> 0 
  974.                 BEGIN
  975.                     RAISERROR (20025, 16, -1, @publication)
  976.                     GOTO FAILURE
  977.                 END
  978.         END
  979.         
  980.         IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties')
  981.         BEGIN
  982.             DELETE FROM MSsubscription_properties 
  983.             WHERE UPPER(publisher) = UPPER(@publisher)  AND
  984.             publisher_db  = @publisher_db AND
  985.             publication = @publication 
  986.     
  987.             IF @@ERROR <> 0 
  988.                 GOTO FAILURE
  989.     
  990.             IF NOT EXISTS (SELECT * FROM MSsubscription_properties)
  991.             BEGIN
  992.                 exec @retcode = dbo.sp_MSsub_cleanup_prop_table
  993.                 IF @@ERROR <> 0 or @retcode <> 0
  994.                     GOTO FAILURE
  995.             END
  996.         END
  997.  
  998.     COMMIT TRAN
  999.  
  1000.     /*
  1001.     ** Set back original settings
  1002.     */
  1003.     IF @reserved = 0
  1004.     BEGIN
  1005.         /* 
  1006.         ** If last subscription is dropped and the DB is not enabled for publishing,
  1007.         ** then remove the merge system tables
  1008.         */
  1009.         IF (not exists (select * from sysmergesubscriptions )) 
  1010.             AND (select category & 4 FROM master..sysdatabases WHERE name = DB_NAME())=0
  1011.         BEGIN
  1012.                 execute @retcode = dbo.sp_MSdrop_mergesystables
  1013.                 if @@ERROR <> 0 or @retcode <> 0
  1014.                     begin
  1015.                         return (1)
  1016.                     end
  1017.         END 
  1018.  
  1019.         IF @implicit_transaction <>0 
  1020.             SET IMPLICIT_TRANSACTIONS ON
  1021.         IF @close_cursor_at_commit <>0 
  1022.             SET CURSOR_CLOSE_ON_COMMIT ON
  1023.     END
  1024.  
  1025.     RETURN(0)       
  1026.  
  1027. FAILURE:
  1028.     RAISERROR (14056, 16, -1)
  1029.     if @@trancount > 0
  1030.     begin
  1031.         ROLLBACK TRANSACTION dropmergepullsubscription
  1032.         COMMIT TRANSACTION
  1033.     end
  1034.     /*
  1035.     ** Set back original settings
  1036.     */  
  1037.     IF @reserved = 0
  1038.     BEGIN
  1039.         IF @implicit_transaction <>0 
  1040.             SET IMPLICIT_TRANSACTIONS ON
  1041.         IF @close_cursor_at_commit <>0 
  1042.             SET CURSOR_CLOSE_ON_COMMIT ON
  1043.     END
  1044.     return 1
  1045. go
  1046. exec sp_MS_marksystemobject 'dbo.sp_dropmergepullsubscription'
  1047. grant execute on dbo.sp_dropmergepullsubscription to public
  1048. --------------------------------------------------------------------------------
  1049. --. sp_MSenum_replsqlqueues
  1050. --------------------------------------------------------------------------------
  1051. if exists (select * from sysobjects
  1052.     where type = 'P' and name = 'sp_MSenum_replsqlqueues')
  1053. drop procedure sp_MSenum_replsqlqueues
  1054. go
  1055. raiserror('Creating procedure sp_MSenum_replsqlqueues', 0,1)
  1056. go
  1057. create procedure sp_MSenum_replsqlqueues
  1058. (
  1059.     @curdistdb    sysname = NULL
  1060. )
  1061. as
  1062. begin
  1063.     declare @distbit int
  1064.     declare @db_name sysname
  1065.     declare @cmd nvarchar(1024)
  1066.  
  1067.     select @distbit = 16
  1068.     --
  1069.     -- security check
  1070.     --
  1071.     if (is_srvrolemember('sysadmin') != 1)
  1072.     begin
  1073.         --
  1074.         -- non SA user
  1075.         -- @curdistdb cannot be null for NON-SA user
  1076.         --
  1077.         if (@curdistdb is null)
  1078.         begin
  1079.             raiserror (14043, 16, -1, '@curdistdb')
  1080.             return 1
  1081.         end
  1082.         else
  1083.         begin
  1084.             --
  1085.             -- The user has to be DBO of the specified distribution db
  1086.             --
  1087.             declare @fisdbo bit
  1088.                     ,@securitycmd nvarchar(300)
  1089.  
  1090.             select @securitycmd = quotename(@curdistdb) + '.dbo.sp_executesql'
  1091.             exec @securitycmd
  1092.                 N'if is_member(N''db_owner'') = 1 set @fisdbo = 1'
  1093.                 ,N'@fisdbo bit output'
  1094.                 ,@fisdbo output 
  1095.             if (@fisdbo != 1)
  1096.             begin
  1097.                 raiserror (21050, 14, 3)
  1098.                 return 1
  1099.             end
  1100.         end
  1101.     end
  1102.     --
  1103.     -- create the temp table to store the relevant information
  1104.     --
  1105.     create table #replqueue (
  1106.         publisher sysname collate database_default not null,
  1107.         publisher_db sysname collate database_default not null,
  1108.         subscriber sysname collate database_default not null,
  1109.         subscriber_db sysname collate database_default not null,
  1110.         publication sysname collate database_default not null,
  1111.         dist_db sysname collate database_default not null
  1112.     )
  1113.     create unique index ucreplqueue ON #replqueue (subscriber, subscriber_db, publication)
  1114.  
  1115.     --
  1116.     -- Has the user specified a distribution database
  1117.     --
  1118.     if (@curdistdb is NULL)
  1119.     begin
  1120.         --
  1121.         -- Go through all the distribution databases
  1122.         --
  1123.         declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR 
  1124.             select name from master.dbo.sysdatabases 
  1125.             where
  1126.                 category & @distbit <> 0 and
  1127.                 has_dbaccess(name) = 1
  1128.             for read only
  1129.     end
  1130.     else
  1131.     begin
  1132.         --
  1133.         -- User specified Distribution Database
  1134.         -- Validate the user specified name
  1135.         --
  1136.         if exists (select name from master.dbo.sysdatabases 
  1137.         where
  1138.             name = @curdistdb and
  1139.             category & @distbit <> 0 and
  1140.             has_dbaccess(name) = 1)
  1141.         begin
  1142.             declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR
  1143.             select @curdistdb
  1144.             for read only
  1145.         end
  1146.         else
  1147.         begin
  1148.             --
  1149.             -- Error : Invalid distribution db specified
  1150.             --
  1151.             raiserror(20587, 16, 3, N'@curdistdb', N'sp_MSenum_replsqlqueues')
  1152.             return 1
  1153.         end
  1154.     end
  1155.     
  1156.     --
  1157.     -- Enumerate
  1158.     --
  1159.     open hCdatabase
  1160.     fetch next from hCdatabase into @db_name
  1161.     while (@@fetch_status <> -1)
  1162.     begin
  1163.         select @cmd =
  1164.         'SET NOCOUNT ON ' +
  1165.         'INSERT INTO #replqueue (publisher, publisher_db, subscriber, subscriber_db, publication, dist_db) ' +
  1166.         'SELECT c.srvname, a.publisher_db, b.srvname, a.subscriber_db, a.publication, N''' + @db_name + ''' ' +
  1167.         'FROM ' + QUOTENAME(@db_name) + '.dbo.MSdistribution_agents as a ' +
  1168.             'JOIN master.dbo.sysservers as b ' +
  1169.             'ON a.subscriber_id = b.srvid ' +
  1170.             'JOIN master.dbo.sysservers as c ' + 
  1171.             'ON a.publisher_id = c.srvid ' + 
  1172.             'WHERE queue_id = N''mssqlqueue'' '
  1173.             
  1174.         exec (@cmd)
  1175.         fetch next from hCdatabase into @db_name
  1176.     end
  1177.     close hCdatabase
  1178.     deallocate hCdatabase
  1179.  
  1180.     --
  1181.     -- select the contents of the temp table
  1182.     --
  1183.     select * from #replqueue
  1184.  
  1185.     --
  1186.     -- cleanup
  1187.     --
  1188.     drop table #replqueue
  1189. end
  1190. go
  1191. EXEC dbo.sp_MS_marksystemobject sp_MSenum_replsqlqueues
  1192. go
  1193. grant execute on dbo.sp_MSenum_replsqlqueues to public
  1194. go
  1195.  
  1196. --------------------------------------------------------------------------------
  1197. --. sp_MSenum_replqueues
  1198. --------------------------------------------------------------------------------
  1199. if exists (select * from sysobjects
  1200.     where type = 'P' and name = 'sp_MSenum_replqueues')
  1201. drop procedure sp_MSenum_replqueues
  1202. go
  1203. raiserror('Creating procedure sp_MSenum_replqueues', 0,1)
  1204. go
  1205. create procedure sp_MSenum_replqueues
  1206. (
  1207.     @curdistdb    sysname = NULL
  1208. )
  1209. as
  1210. begin
  1211.     declare @distbit int
  1212.     declare @db_name sysname
  1213.     declare @cmd nvarchar(1024)
  1214.  
  1215.     select @distbit = 16
  1216.     --
  1217.     -- security check
  1218.     --
  1219.     if (is_srvrolemember('sysadmin') != 1)
  1220.     begin
  1221.         --
  1222.         -- non SA user
  1223.         -- @curdistdb cannot be null for NON-SA user
  1224.         --
  1225.         if (@curdistdb is null)
  1226.         begin
  1227.             raiserror (14043, 16, -1, '@curdistdb')
  1228.             return 1
  1229.         end
  1230.         else
  1231.         begin
  1232.             --
  1233.             -- The user has to be DBO of the specified distribution db
  1234.             --
  1235.             declare @fisdbo bit
  1236.                     ,@securitycmd nvarchar(300)
  1237.  
  1238.             select @securitycmd = quotename(@curdistdb) + '.dbo.sp_executesql'
  1239.             exec @securitycmd
  1240.                 N'if is_member(N''db_owner'') = 1 set @fisdbo = 1'
  1241.                 ,N'@fisdbo bit output'
  1242.                 ,@fisdbo output 
  1243.             if (@fisdbo != 1)
  1244.             begin
  1245.                 raiserror (21050, 14, 3)
  1246.                 return 1
  1247.             end
  1248.         end
  1249.     end
  1250.     --
  1251.     -- create the temp table to store the relevant information
  1252.     --
  1253.     create table #replqueue (
  1254.         queue_server sysname collate database_default not null,
  1255.         queue_id sysname collate database_default not null,
  1256.         dist_db sysname collate database_default not null
  1257.     )
  1258.     create unique clustered index ucreplqueue ON #replqueue (queue_id)
  1259.  
  1260.     --
  1261.     -- Has the user specified a distribution database
  1262.     --
  1263.     if (@curdistdb is NULL)
  1264.     begin
  1265.         --
  1266.         -- Go through all the distribution databases
  1267.         --
  1268.         declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR 
  1269.             select name from master.dbo.sysdatabases 
  1270.             where
  1271.                 category & @distbit <> 0 and
  1272.                 has_dbaccess(name) = 1
  1273.             for read only
  1274.     end
  1275.     else
  1276.     begin
  1277.         --
  1278.         -- User specified Distribution Database
  1279.         -- Validate the user specified name
  1280.         --
  1281.         if exists (select name from master.dbo.sysdatabases 
  1282.         where
  1283.             name = @curdistdb and
  1284.             category & @distbit <> 0 and
  1285.             has_dbaccess(name) = 1)
  1286.         begin
  1287.             declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR
  1288.             select @curdistdb
  1289.             for read only
  1290.         end
  1291.         else
  1292.         begin
  1293.             --
  1294.             -- Error : Invalid distribution db specified
  1295.             --
  1296.             raiserror(20587, 16, 4, N'@curdistdb', N'sp_MSenum_replqueues')
  1297.             return 1
  1298.         end
  1299.     end
  1300.  
  1301.     --
  1302.     -- Enumerate
  1303.     --
  1304.     open hCdatabase
  1305.     fetch next from hCdatabase into @db_name
  1306.     while (@@fetch_status <> -1)
  1307.     begin
  1308.         select @cmd =
  1309.         'SET NOCOUNT ON ' +
  1310.         'INSERT INTO #replqueue (queue_server, queue_id, dist_db) ' +
  1311.         'SELECT queue_server, queue_id, ' +
  1312.                 'N''' + replace(@db_name, '''', '''''') + ''' ' +
  1313.         'FROM ' +
  1314.                 QUOTENAME(@db_name) + '.dbo.MSdistribution_agents ' +
  1315.         'WHERE ' +
  1316.                 'queue_id IS NOT NULL and queue_id != N''mssqlqueue'''
  1317.             
  1318.         exec (@cmd)
  1319.         fetch next from hCdatabase into @db_name
  1320.     end
  1321.     close hCdatabase
  1322.     deallocate hCdatabase
  1323.  
  1324.     --
  1325.     -- select the contents of the temp table to present
  1326.     -- the formatted queue name
  1327.     --
  1328.     select     N'DIRECT=OS:' + queue_server + N'\PRIVATE$\' + queue_id AS 'queue_format'
  1329.             ,dist_db
  1330.     from #replqueue
  1331.     
  1332.     --
  1333.     -- cleanup
  1334.     --
  1335.     drop table #replqueue
  1336. end
  1337. go
  1338. EXEC dbo.sp_MS_marksystemobject sp_MSenum_replqueues
  1339. go
  1340. grant execute on dbo.sp_MSenum_replqueues to public
  1341. go
  1342.  
  1343. --------------------------------------------------------------------------------
  1344. --. sp_vupgrade_publisherdb
  1345. --------------------------------------------------------------------------------
  1346. if exists (select * from sysobjects
  1347.     where type = 'P' and name = 'sp_vupgrade_publisherdb')
  1348. drop procedure sp_vupgrade_publisherdb
  1349. go
  1350. raiserror('Creating procedure sp_vupgrade_publisherdb', 0,1)
  1351. go
  1352. create procedure sp_vupgrade_publisherdb @ver_old int, @ver_retention int
  1353. as
  1354. begin
  1355. /* 
  1356.  * Process schema and metadata changes specific to a publishing database. Transactional replication 
  1357.  * system tables at the publisher are updated by sp_vupgrade_publisherdb; merge tables are not.
  1358.  * Most merge system tables exist in both the publishing and subscribing databases; merge schema 
  1359.  * and metadata changes are processed by a separate pass over all databases in sp_vupgrade_mergetables.
  1360.  *
  1361.  * Match column order of newly created table when adding columns.
  1362.  *
  1363.  * Setup version upgrade procedure call order:
  1364.  *    sp_vupgrade_replication -> sp_vupgrade_publisher -> sp_vupgrade_publisherdb
  1365. */
  1366.  
  1367.     set nocount on 
  1368.  
  1369.     declare @default_name sysname 
  1370.  
  1371.     -- raiserror('sp_vupgrade_publisherdb', 0,1) with nowait
  1372.  
  1373.     -- sysarticles 
  1374.     if exists( select name from sysobjects where name = 'sysarticles' )
  1375.     begin
  1376.         
  1377.         if exists( select * from syscolumns where id = object_id('dbo.sysarticles') and name = 'schema_option' )
  1378.         begin
  1379.             -- The following two-phase upgrade operation has to be atomic
  1380.             begin transaction
  1381.             save transaction sysarticles_upgrade 
  1382.     
  1383.                 -- For table articles which used to have the 
  1384.                 -- SQLDMOCreationScript_DRI_Primary (0x00000080) schema option enabled,
  1385.                 -- turn on the SQLDMOCreationScript_PKFKAsConstraints (0x00008000)
  1386.                 -- option
  1387.                 update sysarticles 
  1388.                    set schema_option = convert(int, schema_option) | convert(int, 0x00008000)
  1389.                   from sysobjects so
  1390.                 where (convert(int, schema_option) & 0x00000080) <> 0x00000000
  1391.                   and so.id = sysarticles.objid
  1392.                   and so.xtype = 'U'
  1393.         
  1394.                 if @@error <> 0
  1395.                     goto SYSARTICLE_ERROR
  1396.  
  1397.                 -- Enable both the SQLDMOCreationScript_DRI_PrimaryKey and
  1398.                 -- SQLDMOCreationScript_UniqueKeys options (0x00004000) if at least 
  1399.                 -- one of SQLDMOCreationScript_NonClusteredIndexes (0x00000010) and 
  1400.                 -- SQLDMOCreationScript_ClusteredIndexes (0x00000040) was enabled
  1401.                 -- or the table article belongs to a transactional publication  
  1402.                 update sysarticles 
  1403.                    set schema_option = convert(int, schema_option) |
  1404.                                         convert(int, 0x00004080)
  1405.                   from sysobjects so,
  1406.                        syspublications sp
  1407.                 where ((sysarticles.pubid = sp.pubid and sp.repl_freq = 0) 
  1408.                       or (convert(int, schema_option) & convert(int, 0x00000050) <> 
  1409.                           0x00000000)) 
  1410.                   and so.id = sysarticles.objid
  1411.                   and so.xtype = 'U'
  1412.  
  1413.                 if @@error <> 0
  1414.                     goto SYSARTICLE_ERROR
  1415.  
  1416.                 -- Skip over the error handling code
  1417.                 goto SYSARTICLE_END
  1418.         SYSARTICLE_ERROR:
  1419.             rollback transaction sysarticles_upgrade
  1420.             commit transaction
  1421.             return 1    
  1422.         SYSARTICLE_END:
  1423.             commit transaction 
  1424.         end
  1425.     end -- end of sysarticles upgrade
  1426.  
  1427.     -- syssubscriptions
  1428.     if exists (select name from sysobjects where name='syssubscriptions')
  1429.     begin
  1430.         if not exists (select * from syscolumns where id = object_id('syssubscriptions') and 
  1431.             name = 'queued_reinit')
  1432.         begin
  1433.             alter table syssubscriptions add queued_reinit bit default 0 not null
  1434.         end
  1435.  
  1436.     end -- end of syssubscriptions upgrade
  1437.  
  1438.     -- syspublications
  1439.     if exists (select name from sysobjects where name='syspublications')
  1440.     begin
  1441.  
  1442.         -- default_access column no longer used
  1443.         if exists (select * from syscolumns where id = object_id('syspublications') and
  1444.             name = 'default_access')
  1445.         begin
  1446.             alter table syspublications drop column default_access
  1447.         end 
  1448.  
  1449.         /*
  1450.          * Queued updating subscriptions option; conflict management settings added later in this proc
  1451.         */
  1452.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1453.             name = 'allow_queued_tran')
  1454.         begin
  1455.             alter table syspublications add allow_queued_tran bit default 0 not null
  1456.         end
  1457.  
  1458.         /*
  1459.          * Portable snapshot
  1460.         */
  1461.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'snapshot_in_defaultfolder')
  1462.         begin
  1463.             alter table syspublications add snapshot_in_defaultfolder bit default 1 not null
  1464.         end
  1465.     
  1466.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'alt_snapshot_folder')
  1467.         begin
  1468.             alter table syspublications add alt_snapshot_folder nvarchar(255) null
  1469.         end
  1470.  
  1471.         /*
  1472.          * Snapshot pre/post commands
  1473.         */
  1474.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'pre_snapshot_script')
  1475.         begin
  1476.             alter table syspublications add pre_snapshot_script nvarchar(255) null
  1477.         end
  1478.        
  1479.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'post_snapshot_script')
  1480.         begin
  1481.             alter table syspublications add post_snapshot_script nvarchar(255) null
  1482.         end
  1483.  
  1484.         /*
  1485.          * Snapshot compression
  1486.         */
  1487.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'compress_snapshot')
  1488.         begin
  1489.             alter table syspublications add compress_snapshot bit default 0 not null
  1490.         end
  1491.  
  1492.         /*
  1493.          * Post SQL7.0 FTP configuration stored at publisher
  1494.         */
  1495.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_address')
  1496.         begin
  1497.             alter table syspublications add ftp_address sysname null
  1498.         end
  1499.  
  1500.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_port')
  1501.         begin
  1502.             alter table syspublications add ftp_port int not null default 21
  1503.         end
  1504.  
  1505.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_subdirectory')
  1506.         begin
  1507.             alter table syspublications add ftp_subdirectory nvarchar(255) null
  1508.         end
  1509.  
  1510.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_login')
  1511.         begin
  1512.             alter table syspublications add ftp_login sysname null default N'anonymous'
  1513.         end
  1514.  
  1515.         if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_password')
  1516.         begin
  1517.             alter table syspublications add ftp_password nvarchar(524) null
  1518.         end
  1519.  
  1520.         -- Since the ftp_address is now required to enable a publication for 
  1521.         -- internet, publications that were enabled for internet can not
  1522.         -- be upgraded automatically. So the enabled for internet option 
  1523.         -- is reset in the upgrade process. 
  1524.         if exists (select * from syscolumns where id = object_id('syspublications') and 
  1525.            name = 'enabled_for_internet')
  1526.         begin
  1527.             update dbo.syspublications 
  1528.                set enabled_for_internet = 0 
  1529.         end
  1530.  
  1531.         /*
  1532.          * Transformable subscriptions
  1533.         */
  1534.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1535.             name = 'allow_dts')
  1536.         begin
  1537.             alter table syspublications add allow_dts bit default 0 not null
  1538.         end
  1539.  
  1540.         /*
  1541.          * Attach & Go 
  1542.         */
  1543.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1544.             name = 'allow_subscription_copy')
  1545.         begin
  1546.             alter table syspublications add allow_subscription_copy bit default 0 not null
  1547.         end
  1548.  
  1549.         /*
  1550.          * Transactional conflict management
  1551.         */
  1552.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1553.             name = 'centralized_conflicts')
  1554.         begin
  1555.             alter table syspublications add centralized_conflicts bit NULL
  1556.         end
  1557.     
  1558.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1559.             name = 'conflict_retention')
  1560.         begin
  1561.             alter table syspublications add conflict_retention int NULL
  1562.         end
  1563.  
  1564.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1565.             name = 'conflict_policy')
  1566.         begin
  1567.             alter table syspublications add conflict_policy int NULL
  1568.         end
  1569.  
  1570.         /*
  1571.          * Attach & Go 
  1572.         */
  1573.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1574.             name = 'queue_type')
  1575.         begin
  1576.             alter table syspublications add queue_type int NULL
  1577.         end
  1578.  
  1579.         /*
  1580.          * Active Directory
  1581.         */
  1582.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1583.             name = 'ad_guidname')
  1584.         begin
  1585.             alter table syspublications add ad_guidname sysname null
  1586.         end
  1587.  
  1588.         if not exists (select * from syscolumns where id = object_id('syspublications') and 
  1589.             name = 'backward_comp_level')
  1590.         begin
  1591.             alter table syspublications add backward_comp_level int default 10 not null
  1592.         end
  1593.         
  1594.         /*
  1595.          * Schema only articles (views, procs, udfs)
  1596.         */
  1597.         if not exists (select * from sysobjects where name = 'sysschemaarticles')
  1598.         begin
  1599.             create table dbo.sysschemaarticles
  1600.             (
  1601.                 artid               int                 NOT NULL,
  1602.                 creation_script     nvarchar(255)       NULL,
  1603.                 description         nvarchar(255)       NULL,
  1604.                 dest_object         sysname             NOT NULL,
  1605.                 name                sysname             NOT NULL,
  1606.                 objid               int                 NOT NULL,
  1607.                 pubid               int                 NOT NULL,
  1608.                 pre_creation_cmd    tinyint             NOT NULL,
  1609.                 status              int                 NOT NULL,
  1610.                 type                tinyint             NOT NULL,
  1611.                 schema_option       binary(8)           NULL,
  1612.                 dest_owner          sysname             NULL
  1613.             )
  1614.             exec dbo.sp_MS_marksystemobject sysschemaarticles
  1615.  
  1616.             if not exists (select * from sysindexes where name = 'unc1sysschemaarticles')
  1617.             begin
  1618.                 create unique nonclustered index unc1sysschemaarticles
  1619.                     on sysschemaarticles(artid, pubid)
  1620.             end  
  1621.  
  1622.         end
  1623.  
  1624.         if exists (select * from sysobjects where name = 'sysextendedarticlesview')
  1625.         begin
  1626.             drop view dbo.sysextendedarticlesview
  1627.         end
  1628.         -- cannot create view directly in stored procedure            
  1629.         exec ( 'create view dbo.sysextendedarticlesview
  1630.                    as
  1631.                    select artid, columns, creation_script, del_cmd, description,
  1632.                    dest_table, filter, filter_clause, ins_cmd, name, objid, pubid, pre_creation_cmd,
  1633.                    status, sync_objid, type, upd_cmd, schema_option, dest_owner    
  1634.                    from sysarticles
  1635.                    union all
  1636.                    select artid, NULL, creation_script, NULL, description,
  1637.                    dest_object, NULL, NULL, NULL, name, objid, pubid, 
  1638.                    pre_creation_cmd, status, NULL, type, NULL, 
  1639.                    schema_option, dest_owner 
  1640.                    from sysschemaarticles' )
  1641.  
  1642.         exec dbo.sp_MS_marksystemobject 'sysextendedarticlesview'
  1643.  
  1644.         exec sp_vupgrade_syscol_status
  1645.  
  1646.     end
  1647.  
  1648.     -- sysarticleupdates
  1649.     if exists (select name from sysobjects where name='sysarticleupdates')
  1650.     begin
  1651.         if not exists (select * from syscolumns where id = object_id('sysarticleupdates') and 
  1652.             name = 'sync_upd_trig')
  1653.         begin
  1654.             alter table sysarticleupdates add sync_upd_trig int default 0 NOT NULL
  1655.         end
  1656.  
  1657.         if not exists (select * from syscolumns where id = object_id('sysarticleupdates') and 
  1658.             name = 'conflict_tableid')
  1659.         begin
  1660.             alter table sysarticleupdates add conflict_tableid int NULL
  1661.         end
  1662.  
  1663.         if not exists (select * from syscolumns where id = object_id('sysarticleupdates') and 
  1664.             name = 'ins_conflict_proc')
  1665.         begin
  1666.             alter table sysarticleupdates add ins_conflict_proc int NULL
  1667.         end
  1668.  
  1669.         if not exists (select * from syscolumns where id = object_id('sysarticleupdates') and 
  1670.             name = 'identity_support')
  1671.         begin
  1672.             alter table sysarticleupdates add identity_support bit default 0 NOT NULL
  1673.         end
  1674.  
  1675.     end
  1676.  
  1677.     -- Upgrade dbt->distbackuplsn
  1678.     -- Make sure the upgrade is done for 8.0 Beta 2 customers.
  1679.     if exists (select * from sysobjects where name = 'sysarticles') and
  1680.         not exists (select * from sysobjects where name = 'systranschemas')
  1681.     begin
  1682.         -- Force to get in even if the logreader is running.
  1683.         exec sp_replflush 
  1684.         exec sp_repldone @xactid = NULL, @xact_segno = NULL, @numtrans = 0,
  1685.             @time = 0, @reset = 0, @code = 1
  1686.         -- Unmark the connection as the logreader.
  1687.         exec sp_replflush
  1688.     end
  1689.  
  1690.     -- Create new tran tables if the db is enabled for tran publishing.
  1691.     if exists (select name from sysobjects where name='syspublications')
  1692.     begin
  1693.         exec dbo.sp_MScreate_pub_tables
  1694.     end
  1695.  
  1696.     /*
  1697.      * syspublications
  1698.     */
  1699.     if exists (select name from sysobjects where name='syspublications')
  1700.     begin
  1701.         if not exists (select * from syscolumns where id = Object_Id('syspublications') and name = 'ftp_password' and length = '1048')
  1702.         begin
  1703.             /*
  1704.              * syspublications ftp_password
  1705.              * no need to upgrade passwords since this column is new in 8.0.
  1706.             */
  1707.             declare @dbname sysname
  1708.             declare @cmptlevel tinyint
  1709.             set @dbname = db_name()
  1710.             select @cmptlevel = cmptlevel from master..sysdatabases where name = @dbname collate database_default
  1711.             if @cmptlevel < 70
  1712.             begin
  1713.                                 raiserror (15048, -1, -1, 70, 70, 70, 80)
  1714.             end
  1715.             else
  1716.             begin
  1717.                 exec( 'alter table syspublications alter column ftp_password nvarchar(524)' )
  1718.             end
  1719.         end
  1720.  
  1721.         -- change non-clustered index on syspublications.pubid to clustered 
  1722.         -- index
  1723.         if exists( select * from sysindexes where name = 'unc1syspublications' and id = object_id('dbo.syspublications') )
  1724.         begin
  1725.            drop index dbo.syspublications.unc1syspublications 
  1726.         end
  1727.         if not exists ( select * from sysindexes where name = 'uc1syspublications' and id = object_id('dbo.syspublications') )
  1728.         begin
  1729.             create unique clustered index uc1syspublications
  1730.                 on syspublications (pubid)
  1731.         end
  1732.     end
  1733. end
  1734. go
  1735. exec dbo.sp_MS_marksystemobject sp_vupgrade_publisherdb
  1736. go
  1737.  
  1738. --------------------------------------------------------------------------------
  1739. --. sp_MSreset_queue
  1740. --------------------------------------------------------------------------------
  1741. if exists (select * from sysobjects
  1742.     where type = 'P' and name = 'sp_MSreset_queue')
  1743. revoke execute on dbo.sp_MSreset_queue from public
  1744.  
  1745. --------------------------------------------------------------------------------
  1746. --. sp_MSscript_begintrig1
  1747. --------------------------------------------------------------------------------
  1748. if exists (select * from sysobjects
  1749.     where type = 'P' and name = 'sp_MSscript_begintrig1')
  1750. revoke execute on dbo.sp_MSscript_begintrig1 from public
  1751.  
  1752. --------------------------------------------------------------------------------
  1753. --. sp_MSscript_begintrig2
  1754. --------------------------------------------------------------------------------
  1755. if exists (select * from sysobjects
  1756.     where type = 'P' and name = 'sp_MSscript_begintrig2')
  1757. revoke execute on dbo.sp_MSscript_begintrig2 from public
  1758.  
  1759. --------------------------------------------------------------------------------
  1760. --. sp_MSscript_endtrig
  1761. --------------------------------------------------------------------------------
  1762. if exists (select * from sysobjects
  1763.     where type = 'P' and name = 'sp_MSscript_endtrig')
  1764. revoke execute on dbo.sp_MSscript_endtrig from public
  1765.  
  1766. --------------------------------------------------------------------------------
  1767. --. sp_MSscript_multirow_trigger
  1768. --------------------------------------------------------------------------------
  1769. if exists (select * from sysobjects
  1770.     where type = 'P' and name = 'sp_MSscript_multirow_trigger')
  1771. revoke execute on dbo.sp_MSscript_multirow_trigger from public
  1772.  
  1773. --------------------------------------------------------------------------------
  1774. --. sp_MSscript_params
  1775. --------------------------------------------------------------------------------
  1776. if exists (select * from sysobjects
  1777.     where type = 'P' and name = 'sp_MSscript_params')
  1778. revoke execute on dbo.sp_MSscript_params from public
  1779.  
  1780. --------------------------------------------------------------------------------
  1781. --. sp_MSscript_pkvar_assignment
  1782. --------------------------------------------------------------------------------
  1783. if exists (select * from sysobjects
  1784.     where type = 'P' and name = 'sp_MSscript_pkvar_assignment')
  1785. revoke execute on dbo.sp_MSscript_pkvar_assignment from public
  1786.  
  1787. --------------------------------------------------------------------------------
  1788. --. sp_MSscript_procbodystart
  1789. --------------------------------------------------------------------------------
  1790. if exists (select * from sysobjects
  1791.     where type = 'P' and name = 'sp_MSscript_procbodystart')
  1792. revoke execute on dbo.sp_MSscript_procbodystart from public
  1793.  
  1794. --------------------------------------------------------------------------------
  1795. --. sp_MSscript_singlerow_trigger
  1796. --------------------------------------------------------------------------------
  1797. if exists (select * from sysobjects
  1798.     where type = 'P' and name = 'sp_MSscript_singlerow_trigger')
  1799. revoke execute on dbo.sp_MSscript_singlerow_trigger from public 
  1800.  
  1801. --------------------------------------------------------------------------------
  1802. --. sp_MSscript_trigger_assignment
  1803. --------------------------------------------------------------------------------
  1804. if exists (select * from sysobjects
  1805.     where type = 'P' and name = 'sp_MSscript_trigger_assignment')
  1806. revoke execute on dbo.sp_MSscript_trigger_assignment from public
  1807.  
  1808. --------------------------------------------------------------------------------
  1809. --. sp_MSscript_trigger_exec_rpc
  1810. --------------------------------------------------------------------------------
  1811. if exists (select * from sysobjects
  1812.     where type = 'P' and name = 'sp_MSscript_trigger_exec_rpc')
  1813. revoke execute on dbo.sp_MSscript_trigger_exec_rpc  from public
  1814.  
  1815. --------------------------------------------------------------------------------
  1816. --. sp_MSscript_trigger_fetch_statement
  1817. --------------------------------------------------------------------------------
  1818. if exists (select * from sysobjects
  1819.     where type = 'P' and name = 'sp_MSscript_trigger_fetch_statement')
  1820. revoke execute on dbo.sp_MSscript_trigger_fetch_statement from public
  1821.  
  1822. --------------------------------------------------------------------------------
  1823. --. sp_MSscript_trigger_update_checks
  1824. --------------------------------------------------------------------------------
  1825. if exists (select * from sysobjects
  1826.     where type = 'P' and name = 'sp_MSscript_trigger_update_checks')
  1827. revoke execute on dbo.sp_MSscript_trigger_update_checks from public
  1828.  
  1829. --------------------------------------------------------------------------------
  1830. --. sp_MSscript_trigger_updates
  1831. --------------------------------------------------------------------------------
  1832. if exists (select * from sysobjects
  1833.     where type = 'P' and name = 'sp_MSscript_trigger_updates')
  1834. revoke execute on dbo.sp_MSscript_trigger_updates from public
  1835.  
  1836. --------------------------------------------------------------------------------
  1837. --. sp_MSclearcolumnbit
  1838. --------------------------------------------------------------------------------
  1839. if exists (select * from sysobjects
  1840.     where type = 'P' and name = 'sp_MSclearcolumnbit')
  1841. revoke execute on dbo.sp_MSclearcolumnbit from public
  1842.  
  1843. --------------------------------------------------------------------------------
  1844. --. sp_MSget_subtypedatasrc
  1845. --------------------------------------------------------------------------------
  1846. if exists (select * from sysobjects
  1847.     where type = 'P' and name = 'sp_MSget_subtypedatasrc')
  1848. revoke execute on dbo.sp_MSget_subtypedatasrc from public
  1849.  
  1850. --------------------------------------------------------------------------------
  1851. --. sp_MSCheckmergereplication
  1852. --------------------------------------------------------------------------------
  1853. if exists (select * from sysobjects
  1854.     where type = 'P' and name = 'sp_MSCheckmergereplication')
  1855. revoke execute on dbo.sp_MSCheckmergereplication from public
  1856.  
  1857. --------------------------------------------------------------------------------
  1858. --. sp_MSremove_userscript
  1859. --------------------------------------------------------------------------------
  1860. if exists (select * from sysobjects
  1861.     where type = 'P' and name = 'sp_MSremove_userscript')
  1862. revoke execute on dbo.sp_MSremove_userscript from public
  1863.  
  1864. --------------------------------------------------------------------------------
  1865. --. sp_MSscript_trigger_variables
  1866. --------------------------------------------------------------------------------
  1867. if exists (select * from sysobjects
  1868.     where type = 'P' and name = 'sp_MSscript_trigger_variables')
  1869. revoke execute on dbo.sp_MSscript_trigger_variables from public
  1870.  
  1871. --------------------------------------------------------------------------------
  1872. --. sp_MSscript_where_clause
  1873. --------------------------------------------------------------------------------
  1874. if exists (select * from sysobjects
  1875.     where type = 'P' and name = 'sp_MSscript_where_clause')
  1876. revoke execute on dbo.sp_MSscript_where_clause from public
  1877.  
  1878. --------------------------------------------------------------------------------
  1879. --. sp_MSupdate_mqserver_subdb
  1880. --------------------------------------------------------------------------------
  1881. if exists (select * from sysobjects
  1882.     where type = 'P' and name = 'sp_MSupdate_mqserver_subdb')
  1883. revoke exec on dbo.sp_MSupdate_mqserver_subdb from public
  1884. go
  1885.  
  1886. --------------------------------------------------------------------------------
  1887. --. sp_MSscript_sync_del_trig
  1888. --------------------------------------------------------------------------------
  1889. if exists (select * from sysobjects
  1890.     where type = 'P' and name = 'sp_MSscript_sync_del_trig')
  1891. drop procedure sp_MSscript_sync_del_trig
  1892. go
  1893. create procedure sp_MSscript_sync_del_trig (
  1894.     @objid        int,
  1895.     @publisher    sysname,
  1896.     @publisher_db sysname,
  1897.     @publication  sysname, 
  1898.     @trigname     sysname,
  1899.     @procname     sysname,
  1900.     @proc_owner      sysname,
  1901.     @cftproc      sysname,
  1902.     @agent_id      int, 
  1903.     @identity_col sysname = NULL,
  1904.     @ts_col       sysname = NULL,
  1905.     @filter_clause nvarchar(4000),
  1906.     @primary_key_bitmap  varbinary(4000)
  1907. )
  1908. as
  1909. BEGIN
  1910.     declare @colname sysname
  1911.             ,@cmd          nvarchar(4000)
  1912.             ,@ins_cmd      nvarchar(4000)
  1913.             ,@columns      binary(32)
  1914.             ,@outvars      nvarchar(4000)
  1915.             ,@rc           int
  1916.             ,@qualname     nvarchar(512)
  1917.             ,@fisqueued       bit
  1918.  
  1919.     set nocount on
  1920.     --
  1921.     -- security check
  1922.     --
  1923.     exec @rc = sp_MSreplcheck_subscribe
  1924.     if @@error <> 0 or @rc <> 0
  1925.     begin
  1926.         return (1)
  1927.     end
  1928.  
  1929.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  1930.     if (LOWER(@cftproc) = N'null')
  1931.     begin
  1932.         select @fisqueued =  0
  1933.                 ,@cftproc = NULL
  1934.     end
  1935.     else 
  1936.         select @fisqueued =  1
  1937.  
  1938.     if @ts_col in ('null','NULL')
  1939.         select @ts_col = null
  1940.  
  1941.     if @identity_col in ('null','NULL')
  1942.         select @identity_col = null
  1943.  
  1944.     -- Create temp table
  1945.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  1946.  
  1947.     -- 1st preamble common to all synctran procs
  1948.     exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'del', @fisqueued
  1949.  
  1950.     -- 2nd preamble common to all synctran procs
  1951.     exec dbo.sp_MSscript_begintrig2 @publisher, @publisher_db, @publication, @objid, 'del', @agent_id, @fisqueued
  1952.  
  1953.     -- script single row handling
  1954.     exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, 
  1955.     @cftproc, @identity_col, @ts_col, 'del', @primary_key_bitmap
  1956.  
  1957.     -- script multi-row handling
  1958.     exec @rc = dbo.sp_MSscript_multirow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, 
  1959.     @cftproc, @identity_col, @ts_col, 'del', @primary_key_bitmap
  1960.  
  1961.     -- script end of trigger
  1962.     exec dbo.sp_MSscript_endtrig 
  1963.  
  1964.     -- send fragments to client
  1965.     select procedure_text from #proctext order by c1 asc
  1966. END
  1967. go
  1968. exec dbo.sp_MS_marksystemobject sp_MSscript_sync_del_trig
  1969. go
  1970. grant execute on dbo.sp_MSscript_sync_del_trig to public
  1971. go
  1972.  
  1973. --------------------------------------------------------------------------------
  1974. --. sp_MSscript_sync_ins_trig
  1975. --------------------------------------------------------------------------------
  1976. if exists (select * from sysobjects
  1977.     where type = 'P' and name = 'sp_MSscript_sync_ins_trig')
  1978. drop procedure sp_MSscript_sync_ins_trig
  1979. go
  1980. raiserror('Creating procedure sp_MSscript_sync_ins_trig', 0,1)
  1981. go
  1982. create procedure sp_MSscript_sync_ins_trig (
  1983.     @objid          int,
  1984.     @publisher    sysname,
  1985.     @publisher_db sysname,
  1986.     @publication  sysname,
  1987.     @trigname     sysname,
  1988.     @procname     sysname,
  1989.     @proc_owner   sysname,
  1990.     @cftproc      sysname,
  1991.     @agent_id      int, 
  1992.     @identity_col sysname = NULL,
  1993.     @ts_col       sysname = NULL,
  1994.     @filter_clause nvarchar(4000),
  1995.     @primary_key_bitmap  varbinary(4000)
  1996. )
  1997. as
  1998. BEGIN
  1999.     declare @colname      sysname
  2000.             ,@cmd          nvarchar(4000)
  2001.             ,@ins_cmd      nvarchar(4000)
  2002.             ,@columns      binary(32)
  2003.             ,@outvars      nvarchar(4000)
  2004.             ,@rc           int
  2005.             ,@qualname     nvarchar(512)
  2006.             ,@fisqueued       bit
  2007.  
  2008.     set nocount on
  2009.     --
  2010.     -- security check
  2011.     --
  2012.     exec @rc = sp_MSreplcheck_subscribe
  2013.     if @@error <> 0 or @rc <> 0
  2014.     begin
  2015.         return (1)
  2016.     end
  2017.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  2018.     if (LOWER(@cftproc) = N'null')
  2019.     begin
  2020.         select @fisqueued =  0
  2021.                 ,@cftproc = NULL
  2022.     end
  2023.     else 
  2024.         select @fisqueued =  1
  2025.  
  2026.     if @ts_col in ('null','NULL')
  2027.         select @ts_col = null
  2028.  
  2029.     if @identity_col in ('null','NULL')
  2030.         select @identity_col = null
  2031.  
  2032.     -- Create temp table
  2033.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  2034.  
  2035.     -- 1st preamble common to all synctran procs
  2036.     exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'ins', @fisqueued
  2037.                 
  2038.     -- 2nd preamble common to all synctran procs
  2039.     exec dbo.sp_MSscript_begintrig2 @publisher, @publisher_db, @publication, @objid, 'ins',@agent_id, @fisqueued
  2040.  
  2041.     -- script single row handling
  2042.     exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, 
  2043.         @cftproc, @identity_col, @ts_col, 'ins', @primary_key_bitmap
  2044.  
  2045.     -- script multi-row handling
  2046.     exec @rc = dbo.sp_MSscript_multirow_trigger @objid, @publisher, @publisher_db, @publication, @procname, @proc_owner, 
  2047.         @cftproc, @identity_col, @ts_col, 'ins', @primary_key_bitmap
  2048.  
  2049.     -- script end of trigger
  2050.     exec dbo.sp_MSscript_endtrig 
  2051.  
  2052.     -- send fragments to client
  2053.     select procedure_text from #proctext order by c1 asc
  2054. END
  2055. go
  2056. exec dbo.sp_MS_marksystemobject sp_MSscript_sync_ins_trig
  2057. go
  2058. grant execute on dbo.sp_MSscript_sync_ins_trig to public
  2059. go
  2060.  
  2061. --------------------------------------------------------------------------------
  2062. --. sp_MSscript_sync_upd_trig
  2063. --------------------------------------------------------------------------------
  2064. if exists (select * from sysobjects
  2065.     where type = 'P' and name = 'sp_MSscript_sync_upd_trig')
  2066. drop procedure sp_MSscript_sync_upd_trig
  2067. go
  2068. raiserror('Creating procedure sp_MSscript_sync_upd_trig', 0,1)
  2069. go
  2070. create procedure sp_MSscript_sync_upd_trig (
  2071.     @objid        int,
  2072.     @publisher    sysname,
  2073.     @publisher_db sysname,
  2074.     @publication  sysname, 
  2075.     @trigname     sysname,
  2076.     @procname     sysname,
  2077.     @proc_owner   sysname,
  2078.     @cftproc      sysname,
  2079.     @agent_id      int, 
  2080.     @identity_col sysname = NULL,
  2081.     @ts_col       sysname = NULL,
  2082.     @filter_clause nvarchar(4000),
  2083.     @primary_key_bitmap  varbinary(4000) )
  2084. as
  2085. BEGIN
  2086.     declare @colname      sysname
  2087.             ,@cmd          nvarchar(4000)
  2088.             ,@ins_cmd      nvarchar(4000)
  2089.             ,@columns      binary(32)
  2090.             ,@outvars      nvarchar(4000)
  2091.             ,@rc           int
  2092.             ,@qualname     nvarchar(512)
  2093.             ,@fisqueued       bit
  2094.  
  2095.     set nocount on
  2096.     --
  2097.     -- security check
  2098.     --
  2099.     exec @rc = sp_MSreplcheck_subscribe
  2100.     if @@error <> 0 or @rc <> 0
  2101.     begin
  2102.         return (1)
  2103.     end
  2104.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  2105.     if (LOWER(@cftproc) = N'null')
  2106.     begin
  2107.         select @fisqueued =  0
  2108.                 ,@cftproc = NULL
  2109.     end
  2110.     else 
  2111.         select @fisqueued =  1
  2112.  
  2113.     if @ts_col in ('null','NULL')
  2114.         select @ts_col = null
  2115.  
  2116.     if @identity_col in ('null','NULL')
  2117.         select @identity_col = null
  2118.  
  2119.     -- Create temp table
  2120.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  2121.  
  2122.     -- 1st preamble common to all synctran procs
  2123.     exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'upd', @fisqueued
  2124.                     
  2125.     -- prevent updating of unique index when 'row compare' conflict detection, since it would trickle
  2126.     -- back as a del/insert, and fail
  2127. /*
  2128.     if @ts_col is null
  2129.     begin
  2130.         insert into #proctext(procedure_text) values(N' 
  2131. ')
  2132. --        exec dbo.sp_MSscript_trigger_update_checks @objid, null, null, 'pk', 0
  2133.     end
  2134. */
  2135.  
  2136.     -- 2nd preamble common to all synctran procs
  2137.     exec dbo.sp_MSscript_begintrig2 @publisher, @publisher_db, @publication, @objid, 'upd',@agent_id, @fisqueued
  2138.  
  2139.     -- script single row handling
  2140.     exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, 
  2141.         @cftproc, @identity_col, @ts_col, 'upd', @primary_key_bitmap
  2142.  
  2143.     -- script multi-row handling
  2144.     exec @rc = dbo.sp_MSscript_multirow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, 
  2145.         @cftproc, @identity_col, @ts_col, 'upd', @primary_key_bitmap
  2146.     -- script end of trigger
  2147.     exec dbo.sp_MSscript_endtrig 
  2148.  
  2149.     -- send fragments to client
  2150.     select procedure_text from #proctext order by c1 asc
  2151. END
  2152. go
  2153. exec dbo.sp_MS_marksystemobject sp_MSscript_sync_upd_trig
  2154. go
  2155. grant execute on dbo.sp_MSscript_sync_upd_trig to public
  2156. go
  2157.  
  2158. --------------------------------------------------------------------------------
  2159. --. sp_check_sync_trigger
  2160. --------------------------------------------------------------------------------
  2161. if exists (select * from sysobjects
  2162.     where type = 'P' and name = 'sp_check_sync_trigger')
  2163. revoke exec on dbo.sp_check_sync_trigger from public
  2164. go
  2165. --------------------------------------------------------------------------------
  2166. --. sp_check_for_sync_trigger
  2167. --------------------------------------------------------------------------------
  2168.  
  2169. if exists (select * from sysobjects
  2170.     where type = 'P' and name = 'sp_check_for_sync_trigger')
  2171. drop procedure sp_check_for_sync_trigger
  2172. go
  2173. raiserror('Creating procedure sp_check_for_sync_trigger', 0,1)
  2174. go
  2175. create proc sp_check_for_sync_trigger 
  2176. (
  2177.     @tabid int, 
  2178.     @trigger_op char(10) = NULL OUTPUT
  2179. )
  2180. as
  2181. begin
  2182.     declare @ins_trigid int
  2183.     declare @upd_trigid int
  2184.     declare @del_trigid int
  2185.     declare @retcode int
  2186.  
  2187.     --
  2188.     -- security check
  2189.     --
  2190.     exec @retcode = sp_MSreplcheck_subscribe
  2191.     if @@error <> 0 or @retcode <> 0
  2192.     begin
  2193.         return (1)
  2194.     end
  2195.  
  2196.     select @trigger_op = NULL
  2197.     
  2198.     select @ins_trigid = id from sysobjects where
  2199.         type = N'TR' and name like N'trg_MSsync_ins_%' and parent_obj = @tabid
  2200.     select @upd_trigid = id from sysobjects where
  2201.         type = N'TR' and name like N'trg_MSsync_upd_%' and parent_obj = @tabid
  2202.     select @del_trigid = id from sysobjects where
  2203.         type = N'TR' and name like N'trg_MSsync_del_%' and parent_obj = @tabid
  2204.  
  2205.     if trigger_nestlevel( @ins_trigid ) > 0
  2206.     begin
  2207.          select @trigger_op = 'ins'
  2208.          return 1
  2209.     end
  2210.     else    -- if nestlevel of insert trigger on same table > 0 then bail
  2211.     if trigger_nestlevel( @upd_trigid ) > 0
  2212.     begin
  2213.          select @trigger_op = 'upd'
  2214.          return 1
  2215.     end
  2216.     else
  2217.     if trigger_nestlevel( @del_trigid ) > 0
  2218.     begin
  2219.          select @trigger_op = 'del'
  2220.          return 1
  2221.     end
  2222.     else
  2223.         return 0
  2224. end
  2225. go
  2226. exec dbo.sp_MS_marksystemobject sp_check_for_sync_trigger
  2227. go
  2228. grant execute on dbo.sp_check_for_sync_trigger to public
  2229. go
  2230.  
  2231. --------------------------------------------------------------------------------
  2232. --. sp_MShelpmergedynamicsnapshotjob
  2233. --------------------------------------------------------------------------------
  2234.  
  2235. if exists (select * from sysobjects
  2236.     where type = 'P' and name = 'sp_MShelpmergedynamicsnapshotjob')
  2237.    drop procedure sp_MShelpmergedynamicsnapshotjob
  2238. go
  2239. raiserror('Creating procedure sp_MShelpmergedynamicsnapshotjob', 0,1)
  2240. go 
  2241. create procedure sp_MShelpmergedynamicsnapshotjob (
  2242.     @publication sysname = N'%',
  2243.     @dynamic_snapshot_jobname sysname = N'%',
  2244.     @dynamic_snapshot_jobid uniqueidentifier = null
  2245.     )
  2246. as
  2247. begin
  2248.     declare @retcode int
  2249.     set nocount on
  2250.     /*
  2251.     ** Security Check
  2252.     */
  2253.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  2254.     IF @@ERROR <> 0 or @retcode <> 0
  2255.         return (1)
  2256.     if not exists (select * from sysobjects where name = 'sysmergepublications')
  2257.     begin
  2258.         return 0
  2259.     end
  2260.  
  2261.     select 'id' = j.id,
  2262.            'job_name' = j.name,
  2263.            'job_id' = j.job_id, 
  2264.            'dynamic_filter_login' = j.dynamic_filter_login,
  2265.            'dynamic_filter_hostname' = j.dynamic_filter_hostname,
  2266.            'dynamic_snapshot_location' = j.dynamic_snapshot_location
  2267.       from sysmergepublications p
  2268.      inner join MSdynamicsnapshotjobs j
  2269.         on p.pubid = j.pubid
  2270.      where (p.name = @publication or @publication = N'%')
  2271.        and (j.name = @dynamic_snapshot_jobname or @dynamic_snapshot_jobname = N'%')
  2272.        and (j.job_id = @dynamic_snapshot_jobid or @dynamic_snapshot_jobid is null) 
  2273.  
  2274.     if @@error <> 0
  2275.         return (1)
  2276.     else
  2277.         return (0)
  2278.  
  2279. end
  2280. go
  2281. exec dbo.sp_MS_marksystemobject sp_MShelpmergedynamicsnapshotjob
  2282. go
  2283. grant execute on dbo.sp_MShelpmergedynamicsnapshotjob to public
  2284. go
  2285. --------------------------------------------------------------------------------
  2286. --. sp_addtabletocontents
  2287. --------------------------------------------------------------------------------
  2288. if exists (select * from sysobjects
  2289.     where type = 'P' and name = 'sp_addtabletocontents')
  2290.    drop procedure sp_addtabletocontents
  2291. go
  2292. raiserror('Creating procedure sp_addtabletocontents', 0,1)
  2293. go
  2294. create procedure sp_addtabletocontents 
  2295.     (@table_name sysname,
  2296.      @owner_name sysname = NULL)
  2297. AS
  2298.  
  2299.     declare @qualified_table_name nvarchar(270)
  2300.     declare @tablenick int
  2301.     declare @tablenickstr nvarchar(12)
  2302.     declare @repl_nick int
  2303.     declare @lineage varbinary(249)
  2304.     declare @colv varbinary(2000)
  2305.     declare @coltrack int
  2306.     declare @objid int
  2307.     declare @maxcolid int
  2308.     declare @retcode int
  2309.     declare @gen int
  2310.  
  2311.     /*
  2312.     ** Security Check
  2313.     */
  2314.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  2315.     IF @@ERROR <> 0 or @retcode <> 0
  2316.         return (1)
  2317.     
  2318.     set nocount on
  2319.     create table #temp_cont(rowguid uniqueidentifier)
  2320.     execute @retcode = dbo.sp_MSgetreplnick @nickname = @repl_nick output
  2321.     if (@@error <> 0) or @retcode <> 0 or @repl_nick IS NULL 
  2322.         begin
  2323.         RAISERROR (14055, 11, -1)
  2324.         RETURN(1)
  2325.         end                 
  2326.  
  2327.     if @owner_name is NULL
  2328.         begin
  2329.         select @owner_name = user_name(uid) from sysobjects where name = @table_name
  2330.         end
  2331.     set @qualified_table_name = QUOTENAME(@owner_name) + '.' + QUOTENAME(@table_name)
  2332.     
  2333.     set @objid = object_id(@qualified_table_name)
  2334.     if @objid is NULL return (1)
  2335.     select @gen = max(gen_cur), @tablenick = max(nickname), @coltrack = max(column_tracking) from sysmergearticles where objid = @objid
  2336.     if @gen is null
  2337.         set @gen = 0
  2338.     select @maxcolid = max(colid) from syscolumns where id = @objid
  2339.  
  2340.     if @coltrack = 1
  2341.         set @colv = { fn INITCOLVS(@maxcolid, @repl_nick) }
  2342.     else
  2343.         set @colv = NULL
  2344.     set @lineage = { fn UPDATELINEAGE(0x0, @repl_nick, 1) }
  2345.  
  2346.     set @tablenickstr = convert(nchar, @tablenick)
  2347.  
  2348.     exec ('insert into #temp_cont(rowguid) select RowGuidCol from ' + @qualified_table_name + ' where
  2349.             RowGuidCol not in (select rowguid from MSmerge_contents where tablenick = 
  2350.             ' + @tablenickstr + ')')
  2351.  
  2352.     insert into MSmerge_contents (tablenick, rowguid, generation, joinchangegen, lineage, colv1)
  2353.         select @tablenick, rowguid, @gen, @gen, @lineage, @colv from #temp_cont
  2354.  
  2355.     drop table #temp_cont
  2356. GO
  2357. exec dbo.sp_MS_marksystemobject sp_addtabletocontents 
  2358. go
  2359. grant exec on dbo.sp_addtabletocontents to public
  2360. go
  2361.  
  2362. --------------------------------------------------------------------------------
  2363. --. sp_MSaddpubtocontents
  2364. --------------------------------------------------------------------------------
  2365. if exists (select * from sysobjects
  2366.     where type = 'P' and name = 'sp_MSaddpubtocontents')
  2367.    drop procedure sp_MSaddpubtocontents
  2368. go
  2369. raiserror('Creating procedure sp_MSaddpubtocontents', 0,1)
  2370. go
  2371. create procedure sp_MSaddpubtocontents 
  2372.     (@publication   sysname)
  2373. AS
  2374.     declare     @pubid  uniqueidentifier
  2375.     declare     @tablenick int
  2376.     declare     @retcode int
  2377.     declare     @objid int
  2378.     declare     @owner sysname
  2379.     declare        @table sysname
  2380.     
  2381.     set nocount on
  2382.     /*
  2383.     ** Security Check
  2384.     */
  2385.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  2386.     IF @@ERROR <> 0 or @retcode <> 0
  2387.         return (1)
  2388.  
  2389.     select @pubid = pubid from sysmergepublications 
  2390.         where name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name()
  2391.     if @pubid is NULL
  2392.         begin
  2393.             raiserror (20026, 11, -1, @publication)
  2394.             return (1)
  2395.         end
  2396.     
  2397.     select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid
  2398.  
  2399.     while @tablenick is not null
  2400.         begin
  2401.         select @objid = objid from sysmergearticles where pubid = @pubid and
  2402.             nickname = @tablenick
  2403.         select @owner = user_name(uid) from sysobjects where id = @objid
  2404.         set @table = OBJECT_NAME(@objid)
  2405.         exec @retcode = dbo.sp_addtabletocontents @table, @owner
  2406.         
  2407.         IF @@ERROR <> 0 or @retcode <> 0
  2408.             return (1)
  2409.  
  2410.         select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid and
  2411.                 nickname > @tablenick
  2412.         end
  2413. GO
  2414. exec dbo.sp_MS_marksystemobject sp_MSaddpubtocontents 
  2415. go
  2416. grant exec on dbo.sp_MSaddpubtocontents to public
  2417. go
  2418.  
  2419. --------------------------------------------------------------------------------
  2420. --. sp_MScomputemergeunresolvedrefs
  2421. --------------------------------------------------------------------------------
  2422.  
  2423. if exists (select * from sysobjects
  2424.     where type = 'P' and name = 'sp_MScomputemergeunresolvedrefs')
  2425.    drop procedure sp_MScomputemergeunresolvedrefs
  2426. go
  2427. raiserror(15339,-1,-1,'sp_MScomputemergeunresolvedrefs')
  2428. GO
  2429. CREATE PROCEDURE sp_MScomputemergeunresolvedrefs
  2430.     @publication sysname, -- Must provide the publication name
  2431.     @article     sysname = '%' -- '%' means all articles in the specified publication, otherwise an exact match is performed
  2432. AS
  2433.     SET NOCOUNT ON 
  2434.     DECLARE @pubid uniqueidentifier 
  2435.  
  2436.     
  2437.     -- Parameter check: @publication
  2438.  
  2439.     IF @publication IS NULL
  2440.     BEGIN
  2441.         RAISERROR (14043, 16, -1, '@publication')
  2442.         RETURN (1)
  2443.     END
  2444.  
  2445.     SELECT @pubid = NULL 
  2446.     -- Get the pubid of the publication
  2447.     SELECT @pubid = pubid 
  2448.       FROM sysmergepublications
  2449.      WHERE name = @publication
  2450.        AND UPPER(publisher) = UPPER(@@SERVERNAME)
  2451.        AND publisher_db = DB_NAME()
  2452.     
  2453.     IF @pubid IS NULL
  2454.     BEGIN
  2455.         RAISERROR (20026, 11, -1, @publication)
  2456.         RETURN (1)    
  2457.     END
  2458.  
  2459.     if ({ fn ISPALUSER(@pubid) } <> 1)
  2460.     begin    
  2461.         RAISERROR (14126, 11, -1)
  2462.         return (1)
  2463.  
  2464.     end    
  2465.  
  2466.     SELECT DISTINCT 
  2467.            'article' = a.name, 
  2468.            'dependent object' = o.name, 
  2469.            'dependent object owner' = u.name, 
  2470.            'dependent objectid' = o.id 
  2471.       FROM dbo.sysmergeextendedarticlesview a
  2472.     INNER JOIN sysdepends dep
  2473.         ON a.objid = dep.id
  2474.        AND a.pubid = @pubid
  2475.        AND (@article = '%' OR name = @article)
  2476.        AND dep.depid NOT IN (SELECT objid FROM dbo.sysmergeextendedarticlesview
  2477.                               WHERE pubid = @pubid 
  2478.                                 AND (@article = '%' OR name = @article))
  2479.     INNER JOIN sysobjects o
  2480.         ON dep.depid = o.id
  2481.     INNER JOIN sysusers u
  2482.         ON u.uid = o.uid          
  2483. GO
  2484.  
  2485. exec dbo.sp_MS_marksystemobject sp_MScomputemergeunresolvedrefs
  2486. go
  2487. grant exec on dbo.sp_MScomputemergeunresolvedrefs to public
  2488. go
  2489.  
  2490. --------------------------------------------------------------------------------
  2491. -- procedures from rlrecon.sql regarding security stuff
  2492. --------------------------------------------------------------------------------
  2493.  
  2494. if exists (select * from sysobjects
  2495.     where type = 'P' and name = 'sp_MSfetchidentityrange')
  2496. drop procedure sp_MSfetchidentityrange
  2497.  
  2498. raiserror('Creating procedure sp_MSfetchidentityrange', 0,1)
  2499. GO
  2500.  
  2501. CREATE PROCEDURE sp_MSfetchidentityrange 
  2502. @tablename            sysname,
  2503. @adjust_only        bit
  2504. AS
  2505.  
  2506. declare @retcode             int
  2507. declare @objid                int
  2508. declare @distributor        sysname
  2509. declare @distribdb            sysname
  2510. declare @publisher            sysname
  2511. declare @publisher_db        sysname
  2512. declare @next_seed            bigint
  2513. declare @range                bigint
  2514. declare @threshold            int
  2515. declare @tablenick             int
  2516. declare @distproc            nvarchar(300)
  2517. declare @identity_support    int
  2518. select @publisher=@@SERVERNAME
  2519. select @publisher_db=db_name()
  2520.  
  2521. select @objid = object_id(@tablename)
  2522.  
  2523. select @identity_support=identity_support, @tablenick = nickname from sysmergearticles where objid=@objid
  2524.  
  2525. /*
  2526. ** do permission checking
  2527. */
  2528. exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
  2529. if @retcode<>0 or @@ERROR<>0 return (1)
  2530.  
  2531.  
  2532. exec @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  2533.         IF @@ERROR <> 0 or @retcode <> 0
  2534.             return (1)
  2535. SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSfetchAdjustidentityrange'
  2536. exec @retcode = @distproc @publisher=@publisher, 
  2537.                             @publisher_db=@publisher_db, 
  2538.                             @tablename=@tablename, 
  2539.                             @adjust_only=1, --do adjust only
  2540.                             @next_seed=@next_seed OUTPUT,
  2541.                             @range=@range OUTPUT,
  2542.                             @threshold=@threshold OUTPUT
  2543. IF @@ERROR <> 0 OR @retcode <> 0
  2544.     return (1)
  2545.  
  2546. --initialize article collection for agents.
  2547. if @adjust_only=0
  2548.     select @identity_support, @next_seed-range, range, threshold from MSrepl_identity_range where  objid = @objid
  2549. GO
  2550. exec dbo.sp_MS_marksystemobject sp_MSfetchidentityrange 
  2551. go
  2552. grant exec on dbo.sp_MSfetchidentityrange to public
  2553. go
  2554.  
  2555. if exists (select * from sysobjects
  2556.     where type = 'P' and name = 'sp_MScheckidentityrange')
  2557. drop procedure sp_MScheckidentityrange
  2558.  
  2559. raiserror('Creating procedure sp_MScheckidentityrange', 0,1)
  2560. GO
  2561.  
  2562. CREATE PROCEDURE sp_MScheckidentityrange 
  2563.     @pubid                 uniqueidentifier,
  2564.     @artname            sysname,
  2565.     @next_seed            bigint,
  2566.     @range                bigint,
  2567.     @threshold            int,
  2568.     @checkonly            int
  2569. AS
  2570.     declare @colid                int
  2571.     declare @colname            sysname
  2572.     declare @retcode            int
  2573.     declare @objid                int
  2574.     declare @identity_so_far    bigint
  2575.     declare @current_max        bigint
  2576.     declare @max_identity        bigint
  2577.     declare @tablename            sysname
  2578.     declare @flag                smallint
  2579.     declare @distributor        sysname
  2580.     declare @distribdb            sysname
  2581.     declare @republisher        bit
  2582.     declare @publisher            sysname
  2583.     declare @publisher_db        sysname
  2584.     declare @distproc            nvarchar(300)
  2585.     declare @pub_range            bigint
  2586.  
  2587.     /*
  2588.     ** Check to see if current publication has permission
  2589.     */
  2590.     if ({ fn ISPALUSER(@pubid) } <> 1)
  2591.     begin    
  2592.         RAISERROR (14126, 11, -1)
  2593.         return (1)
  2594.     end
  2595.     
  2596.     select @objid = objid from sysmergearticles where pubid=@pubid and name=@artname
  2597.     select @flag = 1
  2598.     select @republisher = 0
  2599.     select @tablename=object_name(@objid)
  2600.  
  2601.     if exists (select * from sysmergearticles where objid=@objid and pubid <>@pubid and pubid in (select pubid from 
  2602.                     sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name()))
  2603.     begin
  2604.         select @publisher=@@SERVERNAME
  2605.         select @publisher_db=db_name()
  2606.         select @republisher = 1
  2607.         exec @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  2608.         IF @@ERROR <> 0 or @retcode <> 0
  2609.         begin
  2610.             raiserror(14071, 16, -1)
  2611.             return (1)
  2612.             end
  2613.     end
  2614.  
  2615.     if @checkonly=1
  2616.     begin
  2617.         if @republisher=0
  2618.         begin
  2619.             --current_max is defaulted to max_identity value if not republished at subscribers.
  2620.             select @current_max = current_max from MSrepl_identity_range where objid=@objid
  2621.             select @identity_so_far = ident_current(@tablename)        
  2622.             if ident_incr(@tablename) < 0
  2623.                 select @flag = -1
  2624.             if @flag * 100 * (@identity_so_far - (@current_max + 1 - @range))/@range > @threshold
  2625.                 select 1 --needs bump up
  2626.             else
  2627.                 select 0 --no need to bump up
  2628.         end
  2629.         else
  2630.         begin
  2631.             select @current_max=0, @next_seed=0, @threshold=0, @range=0, @pub_range=0, @max_identity=0  --make them non-NULL
  2632.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MScheck_pub_identity'
  2633.             exec  @retcode=    @distproc @publisher=@@SERVERNAME,
  2634.                                       @publisher_db=@publisher_db,
  2635.                                       @tablename=@tablename,
  2636.                                       @range=@range OUTPUT,
  2637.                                       @max_identity=@max_identity OUTPUT,
  2638.                                       @next_seed = @next_seed OUTPUT,
  2639.                                       @pub_range=@pub_range OUTPUT
  2640.             if @retcode<>0 or @@ERROR<>0
  2641.             begin
  2642.                 raiserror(21195, 16, -1) 
  2643.                 return (1)
  2644.             end
  2645.             if (@max_identity-@next_seed)<@range or (@max_identity-@next_seed)<@pub_range
  2646.                 select 1
  2647.             else
  2648.                 select 0
  2649.         end
  2650.     end
  2651.     else
  2652.     begin
  2653.         if @republisher=0
  2654.         begin
  2655.             --its current_max value is to be set by sp_addmergearticle, if to be republished.
  2656.             update MSrepl_identity_range set max_identity=@next_seed + @range, next_seed=@next_seed, current_max=@next_seed + @range -1
  2657.                 where objid = @objid
  2658.             exec sp_MSreseed @objid, @next_seed, @range 
  2659.             if @@ERROR <> 0 
  2660.                 goto FAILURE
  2661.         end
  2662.         else
  2663.         begin
  2664.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSfetchAdjustidentityrange'
  2665.             exec @retcode = @distproc @publisher=@publisher, 
  2666.                             @publisher_db=@publisher_db, 
  2667.                             @tablename=@tablename, 
  2668.                             @for_publisher = 2,  --for repub case, increment max_identity at distributor side
  2669.                             @next_seed = @next_seed,
  2670.                             @range=@range OUTPUT,
  2671.                             @adjust_only=1 --do adjust only
  2672.             if @retcode<>0 or @@ERROR<>0
  2673.             begin
  2674.                 raiserror(21315, 16, -1, @tablename)
  2675.                 return (1)
  2676.             end
  2677.         end
  2678.     end
  2679.  
  2680.     return (0)
  2681. FAILURE:
  2682.     select 0
  2683.     return (1)
  2684. go
  2685. exec dbo.sp_MS_marksystemobject sp_MScheckidentityrange 
  2686. go
  2687. grant exec on dbo.sp_MScheckidentityrange to public
  2688. go
  2689.  
  2690. if exists (select * from sysobjects
  2691.     where type = 'P' and name = 'sp_MShelpmergearticles')
  2692. drop procedure sp_MShelpmergearticles
  2693.  
  2694. raiserror('Creating procedure sp_MShelpmergearticles', 0,1)
  2695. GO
  2696.  
  2697. CREATE PROCEDURE sp_MShelpmergearticles 
  2698.     @publication sysname,
  2699.     @compatibility_level int = 7000000,
  2700.     @pubidin uniqueidentifier = NULL
  2701. as
  2702.     declare @pubid                     uniqueidentifier
  2703.     declare @artid                     uniqueidentifier
  2704.     declare @user_name                sysname
  2705.     declare @guid_col                sysname
  2706.     declare @identity_support         int
  2707.     declare @nickname                int
  2708.     declare @identity_so_far        bigint
  2709.     declare @next_seed                bigint
  2710.     declare @pub_range                bigint
  2711.     declare @objid                    int
  2712.     declare @qualname                nvarchar(270)
  2713.     declare @retcode                int
  2714.     declare @tablename                sysname
  2715.     declare @range                    bigint
  2716.     declare @current_max            bigint
  2717.     declare @threshold                int
  2718.     declare @distributor            sysname
  2719.     declare @distribdb                sysname
  2720.     declare @distproc                nvarchar(300)
  2721.     declare @flag                    smallint
  2722.     declare @c_max                    bigint
  2723.     declare @n_seed                    bigint
  2724.     declare @db_name                sysname
  2725.     declare @has_joins                int
  2726.     declare @article_filter_category int
  2727.     declare @haspartfilters            int
  2728.     declare @grouppartfilterarticles int
  2729.     declare @injoinfilters            int
  2730.     declare @nofilters                int
  2731.     declare @objid_looper            int
  2732.     declare @indexcol                int
  2733.     declare @rowcount1                int
  2734.     declare @rowcount2                int
  2735.  
  2736.     declare @tmp_table TABLE (tablename sysname, user_name sysname,  
  2737.             guid_col sysname NULL, next_seed bigint, range bigint, threshold int, artid uniqueidentifier, pubid uniqueidentifier, has_joins int, article_filter_category int, objid int, has_relation_with_joinarticles int default 0, node_visited bit default 0)
  2738.     declare @worktable TABLE (objid int NOT NULL, indexcol int)
  2739.  
  2740.     set @nofilters = 1
  2741.     set @haspartfilters = 2
  2742.     set @injoinfilters = 4
  2743.     set @grouppartfilterarticles = 8
  2744.     
  2745.     /*
  2746.     ** To public.
  2747.     */
  2748.     set nocount on
  2749.     if (@publication is null)
  2750.         begin
  2751.         RAISERROR(14003, 16, -1)
  2752.         return (1)
  2753.         end
  2754.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  2755.         begin
  2756.         RAISERROR(20054 , 16, -1)
  2757.         return (1)
  2758.         end
  2759.  
  2760.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  2761.     IF @@ERROR <> 0 or @retcode <> 0
  2762.         return (1)
  2763.  
  2764.     
  2765.     select @db_name = db_name()
  2766.  
  2767.     if @pubidin is not NULL
  2768.         set @pubid = @pubidin
  2769.     else
  2770.         select @pubid = pubid from sysmergepublications
  2771.             where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=@db_name
  2772.  
  2773.     if (@pubid is null)
  2774.         begin
  2775.         RAISERROR (20026, 11, -1, @publication)
  2776.         return (1)
  2777.         end
  2778.  
  2779.     /*
  2780.     ** Check to see if current publication has permission
  2781.     */
  2782.     if ({ fn ISPALUSER(@pubid) } <> 1)
  2783.     begin    
  2784.         RAISERROR (14126, 11, -1)
  2785.         return (1)
  2786.     end
  2787.  
  2788.  
  2789.     select TOP 1 @artid=artid from sysmergearticles where pubid=@pubid order by nickname ASC
  2790.     while (@artid is not NULL)
  2791.     begin
  2792.         select @objid=objid, @nickname=nickname, @identity_support=identity_support from sysmergearticles 
  2793.                 where pubid=@pubid and artid=@artid
  2794.         select @tablename=object_name(@objid)
  2795.         select @user_name=user_name(uid) from sysobjects where id=@objid
  2796.         select @qualname=QUOTENAME(@user_name) + '.' + QUOTENAME(@tablename)
  2797.         select @next_seed=NULL, @range=NULL, @threshold=NULL --null if not being updated later
  2798.         if @identity_support=1 and exists (select * from sysmergepublications where
  2799.             pubid = @pubid and  UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=@db_name)
  2800.         begin
  2801.             select @current_max=0, @next_seed=0, @threshold=0, @range=0, @pub_range=0  --make them non-NULL
  2802.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MScheck_pub_identity'
  2803.             exec  @retcode=    @distproc @publisher=@@SERVERNAME,
  2804.                                       @publisher_db=@db_name,
  2805.                                       @tablename=@tablename,
  2806.                                       @range=@range OUTPUT,
  2807.                                       @current_max=@current_max OUTPUT,
  2808.                                       @threshold=@threshold OUTPUT,
  2809.                                       @next_seed = @next_seed OUTPUT,
  2810.                                       @pub_range=@pub_range OUTPUT
  2811.             if @retcode<>0 or @@ERROR<>0
  2812.                 return (1)
  2813.  
  2814.             select @identity_so_far = IDENT_CURRENT(@tablename)
  2815.             select @flag=1
  2816.             if ident_incr(@tablename) < 0
  2817.                 select @flag = -1
  2818.  
  2819.             -- we attempted to adjust publisher side identity range based on its threshodl if needed
  2820.             -- however, non-dbo/sysadmin's will not be able to do so.
  2821.             -- so this is limited to dbos or sysadmins.
  2822.             if @flag * 100 * (@identity_so_far - (@current_max + 1 - @pub_range))/@pub_range > @threshold
  2823.                     and ((is_srvrolemember('sysadmin') = 1) or (is_member('db_owner') = 1)) 
  2824.             begin
  2825.                 select @c_max=@next_seed + @pub_range - 1
  2826.                 select @n_seed=@next_seed + @pub_range
  2827.                 SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadjust_pub_identity'
  2828.                 exec  @retcode=@distproc @publisher=@@SERVERNAME,
  2829.                                         @publisher_db=@db_name,
  2830.                                         @tablename=@tablename,
  2831.                                         @current_max=@c_max,
  2832.                                         @next_seed = @n_seed
  2833.                 if @retcode<>0 or @@ERROR<>0
  2834.                     return (1)
  2835.  
  2836.                 exec @retcode=sp_MSreseed @objid, @next_seed, @pub_range, 1
  2837.                 if @@ERROR <> 0 or @retcode<>0
  2838.                 begin
  2839.                     raiserror(21197, 16, -1)
  2840.                     return (1)
  2841.                 end
  2842.                 select @next_seed=@next_seed + @pub_range
  2843.  
  2844.             end
  2845.         end
  2846.         else if @identity_support=1 and not exists (select * from sysmergepublications where
  2847.             pubid = @pubid and  UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=@db_name)
  2848.         begin
  2849.             /* This is the case of a message based subscriber acting like publisher */
  2850.             select @range = range, @threshold = threshold, @next_seed = next_seed
  2851.                 from MSrepl_identity_range where objid = @objid
  2852.         end
  2853.  
  2854.         if exists (select * from sysmergesubsetfilters where join_nickname = @nickname)
  2855.             set @has_joins = 1
  2856.         else 
  2857.             set @has_joins = 0
  2858.  
  2859.         -- reset for subsequent bitwise OR operations.
  2860.         set @article_filter_category = 0
  2861.  
  2862.         if exists (select * from sysmergesubsetfilters where pubid = @pubid and (join_nickname = @nickname or art_nickname = @nickname))
  2863.             set @article_filter_category = (@article_filter_category | @injoinfilters)
  2864.         
  2865.         if exists (select * from sysmergearticles where pubid = @pubid and nickname = @nickname and datalength(subset_filterclause) > 1)
  2866.             set @article_filter_category = (@article_filter_category | @haspartfilters | @grouppartfilterarticles)
  2867.         
  2868.         if (@article_filter_category = 0)
  2869.             set @article_filter_category = @nofilters
  2870.  
  2871.         select @guid_col=name from syscolumns where id=@objid and ColumnProperty(@objid, name, 'IsRowGuidCol')=1
  2872.         insert @tmp_table values(@tablename, @user_name, @guid_col, 
  2873.             @next_seed, @range, @threshold, @artid, @pubid, @has_joins, @article_filter_category, @objid, 0, 0)
  2874.         if @@ERROR<>0
  2875.         begin
  2876.             raiserror(21197, 16, -1)
  2877.             return (1)
  2878.         end
  2879.         select @artid = NULL 
  2880.         select TOP 1 @artid=artid from sysmergearticles 
  2881.             where pubid=@pubid and nickname>@nickname order by nickname ASC
  2882.     end
  2883.  
  2884.     -- Find articles that have no relations (in either direction - referring or referenced) with any articles in the join filter category.
  2885.  
  2886.     if exists (select * from @tmp_table where (article_filter_category & @injoinfilters) = @injoinfilters)
  2887.     begin
  2888.  
  2889.         --create unique index #uncworktable on @worktable(objid, indexcol)
  2890.         update @tmp_table set node_visited = 1 
  2891.         where objid not in (select fkeyid from sysreferences)
  2892.         and objid not in (select rkeyid from sysreferences)
  2893.         and (article_filter_category & @injoinfilters) = 0
  2894.  
  2895.         -- get the min objid from the temp table of all articles
  2896.         select @objid_looper = min(objid) from @tmp_table where node_visited = 0
  2897.         
  2898.         while (@objid_looper is not null)
  2899.         begin
  2900.             delete from @worktable
  2901.  
  2902.             select @indexcol = 0
  2903.  
  2904.             insert into @worktable values (@objid_looper, @indexcol)
  2905.                         
  2906.             -- find all the objects referenced by this object and all objects that reference this object.
  2907.             insert into @worktable select distinct rkeyid, @indexcol+1 from sysreferences where fkeyid = @objid_looper
  2908.                                             and rkeyid not in (select objid from @worktable)
  2909.             select @rowcount1 = @@rowcount
  2910.             
  2911.             insert into @worktable select distinct fkeyid, @indexcol+1 from sysreferences where rkeyid = @objid_looper
  2912.                                             and fkeyid not in (select objid from @worktable)
  2913.             select @rowcount2 = @@rowcount
  2914.             
  2915.             while (@rowcount1 <> 0 or @rowcount2 <> 0)
  2916.             begin
  2917.                 
  2918.                 select @indexcol = @indexcol+1
  2919.  
  2920.                 insert into @worktable select distinct s.rkeyid, @indexcol+1 from sysreferences s, @worktable w, @tmp_table t where s.fkeyid = w.objid and w.objid = t.objid
  2921.                                             and w.indexcol = @indexcol and t.node_visited = 0 and s.rkeyid not in (select objid from @worktable)
  2922.                 select @rowcount1 = @@rowcount
  2923.                 
  2924.                 insert into @worktable select distinct s.fkeyid, @indexcol+1 from sysreferences s, @worktable w, @tmp_table t where s.rkeyid = w.objid and w.objid = t.objid
  2925.                                             and w.indexcol = @indexcol and t.node_visited = 0 and s.fkeyid not in (select objid from @worktable)
  2926.                 select @rowcount2 = @@rowcount
  2927.             end
  2928.  
  2929.             if exists (select * from @worktable w, @tmp_table t where w.objid = t.objid and (t.article_filter_category & @injoinfilters) = @injoinfilters)
  2930.             begin
  2931.                 -- all articles in @worktable have a direct or indirect relation with at least one object in the join articles category.
  2932.                 update @tmp_table set node_visited = 1, has_relation_with_joinarticles = 1 
  2933.                 from @tmp_table t, @worktable w 
  2934.                 where w.objid = t.objid 
  2935.             end
  2936.             else
  2937.             begin
  2938.                 -- none of the articles in @worktable has any relation (direct or indirect) with any article in the join articles category.            
  2939.                 update @tmp_table set node_visited = 1, has_relation_with_joinarticles = 0 
  2940.                 from @tmp_table t, @worktable w 
  2941.                 where w.objid = t.objid 
  2942.             end
  2943.  
  2944.             -- process more unvisited articles from @tmp_table
  2945.             select @objid_looper = min(objid) from @tmp_table where objid > @objid_looper and node_visited = 0
  2946.         end
  2947.     end
  2948.     
  2949.     /* If the 7.0 merge agent is making this call then we need to make sure that the CLSID of the sp resolver is the old one and not the new one */
  2950.     if @compatibility_level = 7000000
  2951.         begin
  2952.             begin transaction 
  2953.                 update sysmergearticles set resolver_clsid = '{6F31CE30-7BE4-11d1-9B0A-00C04FC2DEB3}' where article_resolver = 'Microsoft SQLServer Stored Procedure Resolver'
  2954.                 select name, t.tablename, t.user_name, a.artid, pre_creation_command, a.pubid, nickname,
  2955.                     column_tracking, status, resolver_clsid, conflict_script, conflict_table,
  2956.                     insert_proc, update_proc, select_proc, destination_object, missing_col_count, 
  2957.                     missing_cols, t.guid_col, 
  2958.                     article_resolver, resolver_info, subset_filterclause, has_joins, excluded_col_count, 
  2959.                     excluded_cols, destination_owner, identity_support, t.next_seed, t.range, t.threshold, 
  2960.                     verify_resolver_signature, allow_interactive_resolver, fast_multicol_updateproc, check_permissions, t.article_filter_category, t.has_relation_with_joinarticles
  2961.                 from sysmergearticles a, @tmp_table t
  2962.                 where a.artid=t.artid and a.pubid=t.pubid order by a.nickname
  2963.             rollback transaction                
  2964.         end
  2965.     else
  2966.         begin
  2967.             select name, t.tablename, t.user_name, a.artid, pre_creation_command, a.pubid, nickname,
  2968.                 column_tracking, status, resolver_clsid, conflict_script, conflict_table,
  2969.                 insert_proc, update_proc, select_proc, destination_object, missing_col_count, 
  2970.                 missing_cols, t.guid_col, 
  2971.                 article_resolver, resolver_info, subset_filterclause, has_joins, excluded_col_count, 
  2972.                 excluded_cols, destination_owner, identity_support, t.next_seed, t.range, t.threshold, 
  2973.                 verify_resolver_signature, allow_interactive_resolver, fast_multicol_updateproc, check_permissions, t.article_filter_category, t.has_relation_with_joinarticles
  2974.             from sysmergearticles a, @tmp_table t
  2975.             where a.artid=t.artid and a.pubid=t.pubid order by a.nickname
  2976.         end            
  2977.  
  2978.     return (0)    
  2979. go
  2980. exec dbo.sp_MS_marksystemobject sp_MShelpmergearticles 
  2981. go
  2982. grant exec on dbo.sp_MShelpmergearticles to public
  2983. go
  2984.  
  2985. if exists (select * from sysobjects
  2986.     where type = 'P' and name = 'sp_MScreateretry')
  2987. drop procedure sp_MScreateretry
  2988. go
  2989. raiserror('Creating procedure sp_MScreateretry', 0,1)
  2990. GO
  2991.  
  2992. CREATE PROCEDURE sp_MScreateretry 
  2993. as
  2994.     declare @tname sysname
  2995.     declare @pname sysname
  2996.     declare @tempname sysname
  2997.     declare @guid uniqueidentifier
  2998.     declare @guidstr varchar(40)
  2999.     declare @retcode smallint
  3000.  
  3001.     /*
  3002.     ** Check to see if current publication has permission
  3003.     */
  3004.     if not exists (select * from dbo.sysmergepublications 
  3005.                             where 1 = {fn ISPALUSER(pubid)})
  3006.     begin    
  3007.         RAISERROR (14126, 11, -1)
  3008.         return (1)
  3009.     end
  3010.  
  3011.     set @guid = newid()
  3012.     exec @retcode=sp_MSguidtostr @guid, @guidstr out
  3013.     if @retcode<>0 or @@ERROR<>0 return (1)
  3014.     set @tempname = '##retry_' + @guidstr
  3015.  
  3016.     exec @retcode = dbo.sp_MSuniquetempname @tempname, @tempname out
  3017.     if (@@error <> 0) OR @retcode <> 0
  3018.         begin
  3019.         RAISERROR(15001, 16, -1, 'sp_MSuniquetempname')
  3020.         return (1)
  3021.         end
  3022.  
  3023.     exec ('create table ' + @tempname + ' (tablenick int NOT NULL, rowguid uniqueidentifier ROWGUIDCOL default newid() not null, errcode int NOT NULL, errtext nvarchar(255) NULL, type tinyint NOT NULL)' )
  3024.  
  3025.     if (@@error <> 0)
  3026.         begin
  3027.         RAISERROR(15001, 16, -1, @tempname)
  3028.         return (1)
  3029.         end
  3030.  
  3031.     set     @tname = @tempname
  3032.     set @tempname = '##insert_' + @guidstr
  3033.  
  3034.     exec @retcode = dbo.sp_MSuniquetempname @tempname, @tempname out
  3035.     if (@@error <> 0)
  3036.         begin
  3037.         RAISERROR(15001, 16, -1, 'sp_MSuniquetempname')
  3038.         return (1)
  3039.         end
  3040.  
  3041.     exec @retcode = dbo.sp_MSmaketempinsertproc @tname, @tempname
  3042.     if  @@ERROR <>0 or @retcode<>0 return (1)
  3043.  
  3044.     select @pname = @tempname
  3045.     select @tname, @pname
  3046.     return (0)    
  3047. go
  3048. exec dbo.sp_MS_marksystemobject sp_MScreateretry 
  3049. go
  3050. grant exec on dbo.sp_MScreateretry to public
  3051.  
  3052. if exists (select * from sysobjects
  3053.     where type = 'P' and name = 'sp_MSdropretry')
  3054. drop procedure sp_MSdropretry
  3055.  
  3056. raiserror('Creating procedure sp_MSdropretry', 0,1)
  3057. GO
  3058.  
  3059. CREATE PROCEDURE sp_MSdropretry (@tname sysname, @pname sysname)
  3060. as
  3061.     declare @retcode int
  3062.     /*
  3063.     ** To public
  3064.     */
  3065.     if not exists (select * from dbo.sysmergepublications 
  3066.                             where 1 = {fn ISPALUSER(pubid)})
  3067.     begin    
  3068.         RAISERROR (14126, 11, -1)
  3069.         return (1)
  3070.     end
  3071.     
  3072.     exec ('drop table ' + @tname)
  3073.     if @@ERROR <> 0 return(1)
  3074.     exec ('drop procedure ' + @pname)
  3075.     if @@ERROR <> 0 return(1)
  3076.     return (0)    
  3077. go
  3078. exec dbo.sp_MS_marksystemobject sp_MSdropretry 
  3079. go
  3080. grant exec on dbo.sp_MSdropretry to public
  3081. go
  3082.  
  3083.  
  3084. if exists (select * from sysobjects
  3085.     where type = 'P' and name = 'sp_MSenumretries')
  3086. drop procedure sp_MSenumretries
  3087.  
  3088. raiserror('Creating procedure sp_MSenumretries', 0,1)
  3089. GO
  3090.  
  3091. CREATE PROCEDURE sp_MSenumretries
  3092.     (@tname nvarchar(386),
  3093.      @maxrows int,
  3094.      @tablenick int,
  3095.      @rowguid uniqueidentifier)
  3096. as
  3097.     declare @tnstring nvarchar(12)
  3098.     declare @rgstring nvarchar(38)
  3099.     declare @retcode int
  3100.  
  3101.     /*
  3102.     ** do permission checking
  3103.     */
  3104.     exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
  3105.     if @retcode<>0 or @@ERROR<>0 return (1)
  3106.  
  3107.     /*
  3108.     ** Modify temp table, granted to public.
  3109.     */
  3110.  
  3111.     declare @selecttop nvarchar(20)
  3112.     if (@maxrows = 0)
  3113.         set @selecttop= 'select'
  3114.     else
  3115.         set @selecttop= 'select top ' + cast(@maxrows as nvarchar(9)) 
  3116.     
  3117.     if (@tablenick < 1)
  3118.     begin
  3119.         execute (@selecttop + ' tablenick, rowguidcol, errcode, errtext, type from ' + @tname + 
  3120.                  ' order by tablenick, rowguidcol')
  3121.         IF @@ERROR <>0 RETURN (1)          
  3122.     end
  3123.     else
  3124.     begin
  3125.         set @tnstring = convert(nchar, @tablenick)
  3126.         set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
  3127.         execute (@selecttop + ' tablenick, rowguidcol, errcode, errtext, type from ' + @tname + 
  3128.                 ' where (tablenick = ' + @tnstring + ' and  rowguidcol > ' + @rgstring + ') or
  3129.                      tablenick > ' + @tnstring + ' order by tablenick, rowguidcol' )
  3130.         if @@ERROR <> 0 RETURN (1)
  3131.     end
  3132.     return (0)    
  3133. go
  3134. exec dbo.sp_MS_marksystemobject sp_MSenumretries
  3135. go
  3136. grant exec on dbo.sp_MSenumretries to public
  3137.  
  3138. if exists (select * from sysobjects
  3139.     where type = 'P' and name = 'sp_MSdeletepushagent')
  3140. drop procedure sp_MSdeletepushagent
  3141. go
  3142. raiserror('Creating procedure sp_MSdeletepushagent', 0,1)
  3143. GO
  3144.  
  3145. /*
  3146. ** This procedure is obselete for dropping push agent at distribution database.
  3147. ** If we were to recover, don't use server id as parameter for RPC into distributor.
  3148. ** Use server name instead.
  3149. */
  3150. CREATE PROCEDURE sp_MSdeletepushagent (
  3151.     @publisher             sysname,
  3152.     @publisher_db         sysname,
  3153.     @publication         sysname,
  3154.     @subscriber             sysname,
  3155.     @subscriber_db         sysname
  3156.     ) AS
  3157.  
  3158. declare @distributor     sysname
  3159. declare @distribdb        sysname
  3160. declare @pubid            uniqueidentifier
  3161. declare @distproc        nvarchar(300)
  3162. declare @pub_srvid        smallint
  3163. declare @sub_srvid        smallint
  3164. declare @retcode        smallint
  3165.  
  3166. /*
  3167. ** Do permission checking
  3168. */
  3169. exec @retcode=sp_MSreplcheck_publish
  3170. if @retcode<>0 or @@ERROR<>0 return (1)
  3171.  
  3172.  
  3173. EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb   = @distribdb OUTPUT
  3174.         IF @@ERROR <> 0 or @retcode <> 0
  3175.             return (1)
  3176.         
  3177. select @pub_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  3178. select @sub_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  3179. select @pubid=pubid from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db
  3180.  
  3181. SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSdrop_agent_entry'
  3182.  
  3183. EXEC @retcode = @distproc @pub_srvid, @publisher_db, @publication, @sub_srvid, @subscriber_db
  3184.         IF @@ERROR <> 0 OR @retcode <> 0
  3185.             return (1)
  3186. return (0)
  3187. GO
  3188. exec dbo.sp_MS_marksystemobject sp_MSdeletepushagent
  3189. go
  3190. grant exec on dbo.sp_MSdeletepushagent to public
  3191. go
  3192.  
  3193. if exists (select * from sysobjects
  3194.     where type = 'P' and name = 'sp_MSgetlastrecgen')
  3195. drop procedure sp_MSgetlastrecgen
  3196.  
  3197. raiserror('Creating procedure sp_MSgetlastrecgen', 0,1)
  3198. GO
  3199.  
  3200. CREATE PROCEDURE sp_MSgetlastrecgen
  3201.     (@repid uniqueidentifier)
  3202. as
  3203.     declare @pubid         uniqueidentifier
  3204.     declare @pubname     sysname
  3205.     declare @status     int
  3206.     declare @retcode    int
  3207.  
  3208.     /*
  3209.     ** do permission checking
  3210.     */
  3211.     exec @retcode=sp_MSreplcheck_connection @repid = @repid
  3212.     if @retcode<>0 or @@ERROR<>0 return (1)
  3213.  
  3214.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  3215.         begin
  3216.         RAISERROR(20054 , 16, -1)
  3217.         return (1)
  3218.         end
  3219.  
  3220.     if (@repid is null)
  3221.         begin
  3222.             RAISERROR(14043, 16, -1, '@repid')
  3223.             return (1)
  3224.         end
  3225.     /*
  3226.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  3227.     ** metadata cleanup event then return an error so the current merge will quit.
  3228.     */
  3229.     select @pubid = pubid from sysmergesubscriptions where subid = @repid
  3230.     if (@pubid is not null)
  3231.         begin
  3232.             EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  3233.             IF @retcode = 0
  3234.                 BEGIN
  3235.  
  3236.                     select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  3237.                     if @status = 0
  3238.                         begin
  3239.                             RAISERROR(21505, 16, -1, @pubname)
  3240.                             return (1)
  3241.                         end
  3242.                 END
  3243.         end
  3244.  
  3245.     select recgen, recguid from MSmerge_replinfo where repid = @repid
  3246.     return (0)
  3247. go
  3248. exec dbo.sp_MS_marksystemobject sp_MSgetlastrecgen
  3249. go
  3250. grant exec on dbo.sp_MSgetlastrecgen to public
  3251.  
  3252. if exists (select * from sysobjects
  3253.     where type = 'P' and name = 'sp_MSgetlastsentrecgens')
  3254. drop procedure sp_MSgetlastsentrecgens
  3255.  
  3256. raiserror('Creating procedure sp_MSgetlastsentrecgens', 0,1)
  3257. GO
  3258.  
  3259. CREATE PROCEDURE sp_MSgetlastsentrecgens
  3260.     (@repid uniqueidentifier)
  3261. as
  3262.     declare @pubid         uniqueidentifier
  3263.     declare @pubname     sysname
  3264.     declare @status     int
  3265.     declare @retcode    int
  3266.  
  3267.     if (@repid is null)
  3268.         begin
  3269.             RAISERROR(14043, 16, -1, '@repid')
  3270.             return (1)
  3271.         end
  3272.     /*
  3273.     ** do permission checking
  3274.     */
  3275.     exec @retcode=sp_MSreplcheck_connection @repid = @repid
  3276.     if @retcode<>0 or @@ERROR<>0 return (1)
  3277.  
  3278.     /*
  3279.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  3280.     ** metadata cleanup event then return an error so the current merge will quit.
  3281.     */
  3282.     select @pubid = pubid from sysmergesubscriptions where subid = @repid
  3283.     if (@pubid is not null)
  3284.         begin
  3285.             EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  3286.             IF @retcode = 0
  3287.                 BEGIN
  3288.  
  3289.                     select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  3290.                     if @status = 0
  3291.                         begin
  3292.                             RAISERROR(21505, 16, -1, @pubname)
  3293.                             return (1)
  3294.                         end
  3295.                 END
  3296.         end
  3297.  
  3298.     select sentgen, sentguid, recgen, recguid from MSmerge_replinfo where repid = @repid
  3299.     return (0)
  3300. go
  3301. exec dbo.sp_MS_marksystemobject sp_MSgetlastsentrecgens
  3302. go
  3303. grant exec on dbo.sp_MSgetlastsentrecgens to public
  3304. go
  3305.  
  3306. if exists (select * from sysobjects
  3307.     where type = 'P' and name = 'sp_MSgetlastsentgen')
  3308. drop procedure sp_MSgetlastsentgen
  3309.  
  3310. raiserror('Creating procedure sp_MSgetlastsentgen', 0,1)
  3311. GO
  3312.  
  3313. CREATE PROCEDURE sp_MSgetlastsentgen
  3314.     (@repid uniqueidentifier)
  3315. as
  3316.     declare @pubid         uniqueidentifier
  3317.     declare @pubname     sysname
  3318.     declare @status     int
  3319.     declare @retcode    int
  3320.  
  3321.     /*
  3322.     ** do permission checking
  3323.     */
  3324.     exec @retcode=sp_MSreplcheck_connection @repid = @repid
  3325.     if @retcode<>0 or @@ERROR<>0 return (1)
  3326.  
  3327.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  3328.         begin
  3329.         RAISERROR(20054 , 16, -1)
  3330.         return (1)
  3331.         end
  3332.  
  3333.     if (@repid is null)
  3334.         begin
  3335.             RAISERROR(14043, 16, -1, '@repid')
  3336.             return (1)
  3337.         end
  3338.     /*
  3339.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  3340.     ** metadata cleanup event then return an error so the current merge will quit.
  3341.     */
  3342.     select @pubid = pubid from sysmergesubscriptions where subid = @repid
  3343.     if (@pubid is not null)
  3344.         begin
  3345.             EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  3346.             IF @retcode = 0
  3347.                 BEGIN
  3348.  
  3349.                     select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  3350.                     if @status = 0
  3351.                         begin
  3352.                             RAISERROR(21505, 16, -1, @pubname)
  3353.                             return (1)
  3354.                         end
  3355.                 END
  3356.         end
  3357.  
  3358.     select sentgen, sentguid from MSmerge_replinfo where repid = @repid
  3359.     return (0)
  3360. go
  3361. exec dbo.sp_MS_marksystemobject sp_MSgetlastsentgen
  3362. go
  3363. grant exec on dbo.sp_MSgetlastsentgen to public
  3364. go
  3365.  
  3366. if exists (select * from sysobjects
  3367.     where type = 'P' and name = 'sp_MSenumgenerations')
  3368. drop procedure sp_MSenumgenerations
  3369.  
  3370. raiserror('Creating procedure sp_MSenumgenerations', 0,1)
  3371. GO
  3372.  
  3373. CREATE PROCEDURE sp_MSenumgenerations
  3374.     (@genstart int, @pubid uniqueidentifier, @return_count_of_generations bit = 0)
  3375. as
  3376.     declare @retcode     smallint
  3377.     declare @guidnull     uniqueidentifier
  3378.     declare @generation_range TABLE (generation int NOT NULL, guidsrc uniqueidentifier NOT NULL, art_nick int NULL, guidlocal uniqueidentifier NOT NULL, pubid uniqueidentifier NULL, nicknames varbinary(1000) NOT NULL, okaytoskip bit NOT NULL)
  3379.     declare @status     int
  3380.     declare @pubname     sysname
  3381.     declare @rowcount    int
  3382.     set @guidnull = '00000000-0000-0000-0000-000000000000'
  3383.  
  3384.     /*
  3385.     ** Check to see if current publication has permission
  3386.     */
  3387.     if ({ fn ISPALUSER(@pubid) } <> 1)
  3388.     begin    
  3389.         RAISERROR (14126, 11, -1)
  3390.         return (1)
  3391.     end
  3392.  
  3393.     /*
  3394.     ** To public
  3395.     */
  3396.     
  3397.     if (@genstart is null)
  3398.         begin
  3399.         RAISERROR(14043, 16, -1, '@genstart')
  3400.         return (1)
  3401.         end
  3402.     if (@pubid is null)
  3403.         begin
  3404.         RAISERROR(14043, 16, -1, '@pubid')
  3405.         return (1)
  3406.         end
  3407.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  3408.         begin
  3409.         RAISERROR(20054 , 16, -1)
  3410.         return (1)
  3411.         end
  3412.     /*
  3413.     ** Check the publication status at the publisher - if it is inactive ( say because of a 
  3414.     ** metadata cleanup event then return an error so the current merge will quit.
  3415.     */
  3416.     EXEC @retcode = dbo.sp_MScheckatpublisher @pubid
  3417.     IF @retcode = 0
  3418.         BEGIN
  3419.  
  3420.             select @pubname = name, @status = status from sysmergepublications where pubid = @pubid
  3421.             if @status = 0
  3422.                 begin
  3423.                     RAISERROR(21505, 16, -1, @pubname)
  3424.                     return (1)
  3425.                 end
  3426.         END
  3427.  
  3428.     insert into @generation_range (generation, guidsrc, art_nick, guidlocal, pubid, nicknames, okaytoskip)
  3429.     select DISTINCT generation, guidsrc, art_nick, guidlocal, pubid, nicknames, 0
  3430.     from dbo.MSmerge_genhistory 
  3431.     where generation >= @genstart 
  3432.     and (art_nick = 0 or art_nick is NULL or 
  3433.         art_nick in (select nickname from sysmergearticles 
  3434.         where pubid = @pubid)) 
  3435.     select @rowcount = @@rowcount
  3436.  
  3437.     if (@return_count_of_generations = 1)
  3438.         select @rowcount
  3439.  
  3440.     -- optimizations 
  3441.     -- 1. skip all rows that are for incomplete generations for articles that have no joins.
  3442.     -- 2. skip all rows for join articles if all the join article rows are incomplete generations.
  3443.  
  3444.     update @generation_range set okaytoskip = 1
  3445.     where art_nick is not null and art_nick <> 0
  3446.     and guidlocal = @guidnull 
  3447.     and 
  3448.     (
  3449.         (    
  3450.             -- 1. skip all rows that are for incomplete generations for articles that have no joins.
  3451.             not exists (select 1 from sysmergesubsetfilters where join_nickname = art_nick or art_nickname = art_nick)
  3452.         )
  3453.         or
  3454.         (    
  3455.             -- 2. skip all rows for join articles if all the rows for join and joined articles (i.e. the articles represented by join_nickname 
  3456.             --    and art_nickname in sysmergesubsetfilters) are incomplete generations.
  3457.  
  3458.             art_nick in (select join_nickname from sysmergesubsetfilters) 
  3459.             and not exists 
  3460.                 (    
  3461.                     select 1 from @generation_range b where b.guidlocal <> @guidnull 
  3462.                     and exists (select 1 from sysmergesubsetfilters where join_nickname = b.art_nick or art_nickname = b.art_nick)
  3463.                     and b.generation > @genstart
  3464.                 ) 
  3465.         )
  3466.     )
  3467.     
  3468.     select generation, guidsrc, art_nick, guidlocal, pubid, nicknames, okaytoskip from @generation_range
  3469.     ORDER BY generation ASC
  3470.  
  3471.     return (0)
  3472. go
  3473. exec dbo.sp_MS_marksystemobject sp_MSenumgenerations
  3474. go
  3475. grant exec on dbo.sp_MSenumgenerations to public
  3476. go
  3477.  
  3478. if exists (select * from sysobjects
  3479.     where type = 'P' and name = 'sp_MSchecksnapshotstatus')
  3480. drop procedure sp_MSchecksnapshotstatus
  3481.  
  3482. raiserror('Creating procedure sp_MSchecksnapshotstatus', 0,1)
  3483. GO
  3484. CREATE PROCEDURE sp_MSchecksnapshotstatus
  3485.     @publication        sysname
  3486. AS
  3487.     declare @db_name        sysname
  3488.     declare @retention        int
  3489.     declare @snapshot_ready    int
  3490.     declare @pubid            uniqueidentifier
  3491.     declare @last_snapshot     datetime
  3492.     
  3493.     select @snapshot_ready = NULL
  3494.     select @db_name = db_name()
  3495.  
  3496.     select @snapshot_ready=snapshot_ready, @retention=retention, @pubid=pubid
  3497.         from sysmergepublications where name=@publication and publisher=@@SERVERNAME and publisher_db=@db_name
  3498.     if @snapshot_ready is NULL
  3499.         select @snapshot_ready=snapshot_ready, @retention=retention, @pubid=pubid
  3500.             from sysmergepublications where name=@publication
  3501.     if @snapshot_ready is NULL
  3502.     begin
  3503.         raiserror (20026, 11, -1, @publication)
  3504.         return (1)
  3505.     end
  3506.  
  3507.     /*
  3508.     ** Check to see if current publication has permission
  3509.     */
  3510.     if ({ fn ISPALUSER(@pubid) } <> 1)
  3511.     begin    
  3512.         RAISERROR (14126, 11, -1)
  3513.         return (1)
  3514.     end
  3515.     
  3516.     if @snapshot_ready=1 and @retention>0
  3517.     begin
  3518.         select @last_snapshot=last_validated from sysmergesubscriptions where subid=@pubid
  3519.         if dateadd(day, @retention, @last_snapshot)<getdate()
  3520.             select @snapshot_ready=3 /* snapshot is obsolete */
  3521.     end
  3522.     select @snapshot_ready
  3523. go
  3524. exec dbo.sp_MS_marksystemobject sp_MSchecksnapshotstatus
  3525. go
  3526. grant exec on dbo.sp_MSchecksnapshotstatus to public
  3527.  
  3528.  
  3529. if exists (select * from sysobjects
  3530.     where type = 'P' and name = 'sp_MScheckexistsgeneration')
  3531. drop procedure sp_MScheckexistsgeneration
  3532.  
  3533. raiserror('Creating procedure sp_MScheckexistsgeneration', 0,1)
  3534. GO
  3535.  
  3536. CREATE PROCEDURE sp_MScheckexistsgeneration
  3537.     (@genguid uniqueidentifier, @gen int output, @pubid uniqueidentifier = NULL)
  3538. as
  3539.     /*
  3540.     ** Check input parameter
  3541.     */
  3542.     if (@genguid is null)
  3543.         begin
  3544.             RAISERROR(14043, 16, -1, '@genguid')
  3545.             return (1)
  3546.         end
  3547.     /*
  3548.     ** check permission
  3549.     */
  3550.     if @pubid is not NULL
  3551.     begin
  3552.         if ({ fn ISPALUSER(@pubid) } <> 1)
  3553.         begin    
  3554.             RAISERROR (14126, 11, -1)
  3555.             return (1)
  3556.  
  3557.         end
  3558.     end
  3559.     else
  3560.     begin
  3561.         if not exists (select * from dbo.sysmergepublications 
  3562.                                 where 1 = {fn ISPALUSER(pubid)})
  3563.         begin
  3564.             RAISERROR (14126, 11, -1)
  3565.             return (1)
  3566.         end    
  3567.     end    
  3568.     /* Normal case : do not qualify by pubid */
  3569.     if (@pubid IS NULL)
  3570.         select @gen = max(generation) from dbo.MSmerge_genhistory where guidsrc = @genguid and guidlocal <> '00000000-0000-0000-0000-000000000000'
  3571.     else        
  3572.     /* If we are reinitializing from an alternate publisher, check if the subscription has received generations for the alternate publication */
  3573.         select @gen = max(generation) from dbo.MSmerge_genhistory where guidsrc = @genguid and guidlocal <> '00000000-0000-0000-0000-000000000000'
  3574.             and ((pubid = @pubid) or (pubid is null))
  3575.     IF @@ERROR <>0 return (1)
  3576.     return (0)
  3577. go
  3578. exec dbo.sp_MS_marksystemobject sp_MScheckexistsgeneration
  3579. go
  3580. grant exec on dbo.sp_MScheckexistsgeneration to public
  3581. GO
  3582.  
  3583. if exists (select * from sysobjects
  3584.     where type = 'P' and name = 'sp_MSenumreplicas')
  3585. drop procedure sp_MSenumreplicas
  3586. raiserror('Creating procedure sp_MSenumreplicas', 0,1)
  3587. GO
  3588.  
  3589. CREATE PROCEDURE sp_MSenumreplicas (@pubid uniqueidentifier)
  3590. as
  3591.     declare @inactive tinyint
  3592.  
  3593.     /*
  3594.     ** Check to see if current publication has permission
  3595.     */
  3596.     if ({ fn ISPALUSER(@pubid) } <> 1)
  3597.     begin    
  3598.         RAISERROR (14126, 11, -1)
  3599.         return (1)
  3600.     end
  3601.  
  3602.     /*
  3603.     ** To public
  3604.     */
  3605.  
  3606.     select @inactive = 0
  3607.     if (not exists(select * from sysobjects where name = 'MSmerge_contents'))
  3608.     begin
  3609.         RAISERROR(20054 , 16, -1)
  3610.         return (1)
  3611.     end
  3612.  
  3613.     select subs.subid, replinfo.replnickname, subs.subscriber_type, subs.subscription_type, 
  3614.         subs.priority, replinfo.schemaversion, replinfo.schemaguid, subs.datasource_type, subs.datasource_path, servers.srvname,  
  3615.         subs.db_name, subs.status, subs.partnerid, subs.sync_type, subs.description, subs.pubid, subs.publication, subs.distributor
  3616.         from sysmergesubscriptions subs, MSmerge_replinfo replinfo, master..sysservers servers
  3617.             where replinfo.repid = subs.subid 
  3618.                 and subs.srvid = servers.srvid
  3619.                 and subs.status <> @inactive
  3620.                 and subs.subscriber_type = 1
  3621.                 order by convert(binary, subs.subid)
  3622.     IF @@ERROR <>0 return (1) 
  3623.     return (0)
  3624. go
  3625. exec dbo.sp_MS_marksystemobject sp_MSenumreplicas 
  3626. go
  3627. grant exec on dbo.sp_MSenumreplicas to public
  3628.  
  3629. if exists (select * from sysobjects
  3630.     where type = 'P' and name = 'sp_MSenumpartialdeletes')
  3631. drop procedure sp_MSenumpartialdeletes
  3632. go
  3633. raiserror('Creating procedure sp_MSenumpartialdeletes', 0,1)
  3634. GO
  3635.  
  3636. CREATE PROCEDURE sp_MSenumpartialdeletes
  3637.     (@maxrows int,
  3638.      @tablenick int,
  3639.      @rowguid uniqueidentifier,
  3640.      @tablenotbelongs nvarchar(255),
  3641.      @bookmark int = NULL,
  3642.      @specified_article_only int = 0)
  3643. as
  3644.  
  3645.     declare @tnstring         nvarchar(12)
  3646.     declare @rgstring         nvarchar(38)
  3647.     declare @lowrangestr     nvarchar(12) 
  3648.     declare @highrangestr     nvarchar(12) 
  3649.     declare @retcode        int
  3650.     
  3651.     /*
  3652.     ** do permission checking
  3653.     */
  3654.     exec @retcode=sp_MSreplcheck_connection @tablenick = @tablenick
  3655.     if @retcode<>0 or @@ERROR<>0 return (1)
  3656.  
  3657.     /*
  3658.     ** To public.
  3659.     */
  3660.     
  3661.     declare @selecttop nvarchar(20)
  3662.     if (@maxrows = 0)
  3663.         set @selecttop= 'select'
  3664.     else
  3665.         set @selecttop= 'select top ' + cast(@maxrows as nvarchar(9)) 
  3666.  
  3667. -- DEBUG    insert into MSmerge_debug
  3668. -- DEBUG        (okay, artnick, twhen, comment)
  3669. -- DEBUG        values (0, @tablenick, getdate(), 'sp_MSenumpartialdeletes; maxrows=' + convert(nvarchar, @maxrows) 
  3670. -- DEBUG        + ', startguid=' + convert(nchar(36), @rowguid) + ', bookmark=' + convert(nvarchar, @bookmark)
  3671. -- DEBUG        + ', specified_article_only=' + convert(nchar(1), @specified_article_only))
  3672.  
  3673.     if (@tablenick < 1)
  3674.     begin
  3675.         execute (@selecttop + ' tablenick, rowguid, COALESCE (generation, 0), lineage, type, bookmark from ' + @tablenotbelongs + '
  3676.                     order by tablenick desc, rowguid asc' )
  3677.         IF @@ERROR <>0 
  3678.         begin
  3679. -- DEBUG    insert into MSmerge_debug (okay, twhen, comment)
  3680. -- DEBUG        values (1, getdate(), 'sp_MSenumpartialdeletes: select from notbelong failed')
  3681.             return (1)     
  3682.         end
  3683.  
  3684. -- DEBUG    execute ('insert into MSmerge_debug (okay, artnick, rowguid, generation_new, lineage_new, twhen, comment) ' +
  3685. -- DEBUG                @selecttop + ' 0, tablenick, rowguid, COALESCE (generation, 0), lineage, getdate(), ''sp_MSenumpartialdeletes'' 
  3686. -- DEBUG                from ' + @tablenotbelongs + ' order by tablenick desc, rowguid asc' )
  3687.     end
  3688.     else 
  3689.     begin
  3690.         set @tnstring = convert(nchar, @tablenick)
  3691.         set @rgstring = '''' + convert(nchar(36), @rowguid) + ''''
  3692.  
  3693.         /* 
  3694.         ** If a 7.0 SP1 Merge agent is calling this sp, it passed a valid bookmark parameter 
  3695.         ** Use the bookmark column in the ##belongs_<> table to retrieve the next batch of rows
  3696.         */
  3697.         if @bookmark is NOT NULL 
  3698.         begin
  3699.             set @lowrangestr = convert(nchar, @bookmark)
  3700.             set @highrangestr = convert(nchar, (@bookmark + @maxrows))
  3701.  
  3702.             if (@specified_article_only = 1)
  3703.             begin
  3704.                 -- don't rely on @highrangestr since it will be equal to @lowrangestr if @maxrows=0.
  3705.                 execute (@selecttop + ' tablenick, rowguid, COALESCE (generation, 0), lineage, type, bookmark from ' + @tablenotbelongs + '
  3706.                             where  tablenick = ' + @tnstring + ' and 
  3707.                             bookmark > ' + @lowrangestr + ' 
  3708.                             order by rowguid' )
  3709.  
  3710.                 if @@ERROR<>0
  3711.                 begin
  3712. -- DEBUG            insert into MSmerge_debug (okay, twhen, comment)
  3713. -- DEBUG            values (2, getdate(), 'sp_MSenumpartialdeletes: select from notbelong failed')
  3714.                     return (1)
  3715.                 end                        
  3716.  
  3717. -- DEBUG        execute ('insert into MSmerge_debug (okay, artnick, rowguid, generation_new, lineage_new, type, twhen, comment) ' + 
  3718. -- DEBUG                    @selecttop + ' 0, tablenick, rowguid, COALESCE (generation, 0), lineage, type, getdate(), ''sp_MSenumpartialdeletes: @specified_article_only = 1''
  3719. -- DEBUG                    from ' + @tablenotbelongs + '
  3720. -- DEBUG                    where  tablenick = ' + @tnstring + ' and 
  3721. -- DEBUG                    bookmark > ' + @lowrangestr + ' 
  3722. -- DEBUG                    order by rowguid' )
  3723.  
  3724.             end
  3725.             else
  3726.             begin
  3727.                 execute ('select tablenick, rowguid, COALESCE (generation, 0), lineage, type, bookmark from ' + @tablenotbelongs + '
  3728.                             where  ((tablenick = ' + @tnstring + ' and 
  3729.                             bookmark > ' + @lowrangestr + ' and bookmark <= ' + @highrangestr + ') or
  3730.                             tablenick < ' + @tnstring + ') 
  3731.                             order by tablenick desc, rowguid asc' )
  3732.  
  3733.                 if @@ERROR<>0
  3734.                 begin
  3735. -- DEBUG            insert into MSmerge_debug (okay, twhen, comment)
  3736. -- DEBUG                values (3, getdate(), 'sp_MSenumpartialdeletes: select from notbelong failed')
  3737.                     return (1)
  3738.                 end                        
  3739.  
  3740. -- DEBUG        execute ('insert into MSmerge_debug (okay, artnick, rowguid, generation_new, lineage_new, type, twhen, comment)
  3741. -- DEBUG                    select 0, tablenick, rowguid, COALESCE (generation, 0), lineage, type, getdate(), ''sp_MSenumpartialdeletes: @specified_article_only <> 1'' 
  3742. -- DEBUG                    from ' + @tablenotbelongs + '
  3743. -- DEBUG                    where  ((tablenick = ' + @tnstring + ' and 
  3744. -- DEBUG                    bookmark > ' + @lowrangestr + ' and bookmark <= ' + @highrangestr + ') or
  3745. -- DEBUG                    tablenick < ' + @tnstring + ') 
  3746. -- DEBUG                    order by tablenick desc, rowguid asc' )
  3747.             end
  3748.         end
  3749.  
  3750.         /* 
  3751.         ** Backward compatibilty mode : If a 7.0 Merge agent is calling this sp, it will pass a NULL bookmark parameter 
  3752.         ** Use the rowguid and set rowcount to retrieve the next batch of rows
  3753.         */
  3754.         else
  3755.         begin
  3756.             if (@specified_article_only = 1)
  3757.             begin
  3758.                 execute (@selecttop + ' tablenick, rowguid, COALESCE (generation, 0), lineage, type from ' + @tablenotbelongs + '
  3759.                             where  tablenick = ' + @tnstring + ' and rowguid > ' + @rgstring + '
  3760.                             order by rowguid' )
  3761.                 IF @@ERROR <>0 
  3762.                 begin
  3763. -- DEBUG                insert into MSmerge_debug (okay, twhen, comment)
  3764. -- DEBUG                values (4, getdate(), 'sp_MSenumpartialdeletes: select from notbelong failed')
  3765.                     return (1)     
  3766.                 end
  3767.  
  3768. -- DEBUG                execute ('insert into MSmerge_debug (okay, artnick, rowguid, generation_new, lineage_new, type, twhen, comment) ' + 
  3769. -- DEBUG                    @selecttop + ' 0, tablenick, rowguid, COALESCE (generation, 0), lineage, type, getdate(), ''sp_MSenumpartialdeletes: @specified_article_only = 0''
  3770. -- DEBUG                    from ' + @tablenotbelongs + '
  3771. -- DEBUG                    where  tablenick = ' + @tnstring + ' and 
  3772. -- DEBUG                    rowguid > ' + @rgstring + ' 
  3773. -- DEBUG                    order by rowguid' )
  3774.             end
  3775.             else
  3776.             begin
  3777.                 execute (@selecttop + ' tablenick, rowguid, COALESCE (generation, 0), lineage, type from ' + @tablenotbelongs + '
  3778.                             where  ((tablenick = ' + @tnstring + ' and 
  3779.                             rowguid > ' + @rgstring + ') or tablenick < ' + @tnstring + ') 
  3780.                             order by tablenick desc, rowguid asc' )
  3781.                 IF @@ERROR <>0 
  3782.                 begin
  3783. -- DEBUG                insert into MSmerge_debug (okay, twhen, comment)
  3784. -- DEBUG                values (5, getdate(), 'sp_MSenumpartialdeletes: select from notbelong failed')
  3785.                     return (1)     
  3786.                 end
  3787.  
  3788. -- DEBUG                execute ('insert into MSmerge_debug (okay, artnick, rowguid, generation_new, lineage_new, type, twhen, comment) ' + 
  3789. -- DEBUG                    @selecttop + ' 0, tablenick, rowguid, COALESCE (generation, 0), lineage, type, getdate(), ''sp_MSenumpartialdeletes: @specified_article_only = 0''
  3790. -- DEBUG                    from ' + @tablenotbelongs + '
  3791. -- DEBUG                    where  ((tablenick = ' + @tnstring + ' and 
  3792. -- DEBUG                    rowguid > ' + @rgstring + ') or tablenick < ' + @tnstring + ')
  3793. -- DEBUG                    order by tablenick desc, rowguid asc' )
  3794.             end
  3795.         end
  3796.     end
  3797.     return (0)
  3798. go        
  3799. exec dbo.sp_MS_marksystemobject sp_MSenumpartialdeletes
  3800. go
  3801. grant exec on dbo.sp_MSenumpartialdeletes to public
  3802. go
  3803.  
  3804. if exists (select * from sysobjects
  3805.     where type = 'P '
  3806.             and name = 'sp_MSaddanonymousreplica')
  3807.     drop procedure sp_MSaddanonymousreplica
  3808. go
  3809. raiserror('Creating procedure sp_MSaddanonymousreplica',0,1)
  3810. GO
  3811. CREATE PROCEDURE sp_MSaddanonymousreplica
  3812.     (@publication         sysname,
  3813.      @publisher            sysname,
  3814.      @publisherDB        sysname,
  3815.      @anonymous            int,
  3816.      @sync_type            int = 1, /* sync type is automatic by default */
  3817.      @preexists            bit=0 OUTPUT
  3818. )
  3819. as
  3820. set nocount on
  3821. declare @retcode                 int
  3822. declare @subscription_type         nvarchar(15)
  3823. declare @sync_typestr             nvarchar(15)
  3824. declare @sub_typeid                int
  3825. declare @pubid                    uniqueidentifier
  3826.  
  3827. /*
  3828. ** need more than PAL to do this.
  3829. */
  3830. exec @retcode = sp_MSreplcheck_subscribe
  3831. if @@error<>0 or @retcode<>0
  3832.     return (1)
  3833.  
  3834. select @preexists = 0
  3835.  
  3836. if @anonymous = 1 
  3837. begin
  3838.     select @subscription_type = 'anonymous'
  3839.     select @sub_typeid    = 2 --subscription type value for anonymous
  3840. end
  3841. else 
  3842. begin
  3843.     select @subscription_type = 'local'
  3844.     select @sub_typeid = 1 --subscription type value for well known pull
  3845. end
  3846.  
  3847. if @sync_type = 1 select @sync_typestr = 'automatic'
  3848.     else select @sync_typestr = 'none'
  3849.  
  3850. -- this change is made so that we will try to add pull/anonymous subscriptions, even if
  3851. -- there is a already a subscription for that publication, however the subscription type
  3852. -- does not match. In this way we can prevent users from using incorrect subscription type
  3853. -- through command line or merge control. 
  3854.  
  3855. if exists (select * from sysobjects where name='sysmergepublications')
  3856. begin
  3857.     select @pubid=pubid from sysmergepublications 
  3858.         where name=@publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisherDB
  3859.     if @pubid is not NULL
  3860.     begin
  3861.         /* Check if theres is a subscriptions entry that matches the pubid and current subscription with the right type */
  3862.         if exists (select * from sysmergesubscriptions where pubid =@pubid  and UPPER(subscriber_server) = @@SERVERNAME and db_name = DB_NAME() and subscription_type=@sub_typeid)
  3863.             begin
  3864.                 select @preexists = 1
  3865.                 return (0)   -- replica exists. 
  3866.             end
  3867.         /* 
  3868.         ** Check if theres is a subscriptions entry that matches the pubid and current subscription - 
  3869.         ** If there is a match and the types are not the same, then return appropriate error.
  3870.         */
  3871.         else if exists (select * from sysmergesubscriptions where pubid =@pubid  and UPPER(subscriber_server) = @@SERVERNAME and db_name = DB_NAME())
  3872.             begin
  3873.             RAISERROR (21500, 16, -1, @publication)    
  3874.             -- replica exists with wrong subscription type 
  3875.             select @preexists = 1
  3876.  
  3877.             return (1)   
  3878.             end
  3879.         
  3880.     end
  3881. end
  3882.  
  3883. -- Call this SP to add this replica
  3884. exec @retcode = dbo.sp_addmergepullsubscription 
  3885.     @publication = @publication,
  3886.     @publisher = @publisher,
  3887.     @publisher_db=@publisherDB,
  3888.     @subscriber_type =@subscription_type,
  3889.     @sync_type = @sync_typestr
  3890.  
  3891. IF @retcode<>0 or @@ERROR<>0 return (1)
  3892. return (0)
  3893. GO
  3894. exec dbo.sp_MS_marksystemobject sp_MSaddanonymousreplica
  3895. go
  3896. grant execute on dbo.sp_MSaddanonymousreplica to public
  3897. go 
  3898.  
  3899. --------------------------------------------------------------------------------
  3900. --. sp_helpreplfailovermode
  3901. --------------------------------------------------------------------------------
  3902.  
  3903. if exists (select * from sysobjects
  3904.     where type = 'P' and name = 'sp_helpreplfailovermode')
  3905. drop procedure sp_helpreplfailovermode
  3906. go
  3907. raiserror('Creating procedure sp_helpreplfailovermode', 0,1)
  3908. go
  3909. create procedure sp_helpreplfailovermode (
  3910.     @publisher sysname,
  3911.     @publisher_db sysname,
  3912.     @publication sysname,
  3913.     @failover_mode_id tinyint = 0 output,
  3914.     @failover_mode nvarchar(10) = NULL output)
  3915. as
  3916. BEGIN
  3917.     declare    @subfound bit
  3918.             ,@retcode int
  3919.  
  3920.     --
  3921.     -- security check
  3922.     --
  3923.     exec @retcode = sp_MSreplcheck_subscribe
  3924.     if @@error <> 0 or @retcode <> 0
  3925.     begin
  3926.         return (1)
  3927.     end
  3928.     --
  3929.     -- Check if the table MSsubscription_agents exists
  3930.     --
  3931.     if exists (select * from dbo.sysobjects 
  3932.                     where name = 'MSsubscription_agents')
  3933.     begin
  3934.         --
  3935.         -- Only valid to get failover_mode, if failover_mode is failover (3,5)
  3936.         --
  3937.         if exists (select * from dbo.MSsubscription_agents
  3938.                 where publisher = @publisher and 
  3939.                     publisher_db = @publisher_db and
  3940.                     publication = @publication and
  3941.                     update_mode in (3,5) )
  3942.             select @subfound = 1
  3943.         else
  3944.             select @subfound = 0
  3945.     end
  3946.     else
  3947.         select @subfound = 0
  3948.     
  3949.     --
  3950.     -- Did we find an entry for initialized failover subscription
  3951.     --
  3952.     if (@subfound = 0)
  3953.     begin
  3954.         --
  3955.         -- Three possibilities : uninitialized subscription, non existent subscription
  3956.         -- or a non-mixed mode. Check If we have a PULL uninitialized subscription
  3957.         --
  3958.         if exists (select * from dbo.sysobjects 
  3959.                         where name = 'MSreplication_subscriptions')
  3960.         begin
  3961.             if exists (select * from dbo.MSreplication_subscriptions
  3962.                             where publisher = @publisher and 
  3963.                                 publisher_db = @publisher_db and
  3964.                                 publication = @publication and
  3965.                                 update_mode in (3,5) )
  3966.             begin
  3967.                 --
  3968.                 -- unitialized PULL subscription : return the default values
  3969.                 --
  3970.                 select @failover_mode_id = 0
  3971.                 select @subfound = 1
  3972.             end
  3973.         end
  3974.  
  3975.         if (@subfound = 0)
  3976.         begin
  3977.             raiserror ('sp_helpreplfailovermode: Subscription for [%s].[%s].[%s] either has not been initialized or does not exist or does not support mixed mode',
  3978.                         16, 1, @publisher, @publisher_db, @publication)
  3979.             return 1
  3980.         end
  3981.     end
  3982.     else
  3983.     begin
  3984.         --
  3985.         -- we found our subscription
  3986.         --
  3987.         select @failover_mode_id = failover_mode
  3988.         from dbo.MSsubscription_agents
  3989.         where publisher = @publisher and 
  3990.             publisher_db = @publisher_db and
  3991.             publication = @publication and
  3992.             update_mode in (3,5) 
  3993.             
  3994.         --
  3995.         -- initialize to 'immediate' if necessary
  3996.         --
  3997.         if @failover_mode_id not in (0, 1)
  3998.         begin
  3999.             raiserror ('sp_helpreplfailovermode: invalid failover_mode value %d for [%s].[%s].[%s], setting to 0 [immediate]', 
  4000.                 11, 1, @failover_mode_id, @publisher, @publisher_db, @publication)
  4001.             update dbo.MSsubscription_agents 
  4002.             set failover_mode = 0
  4003.             where publisher = @publisher and 
  4004.                 publisher_db = @publisher_db and
  4005.                 publication = @publication and
  4006.                 update_mode in (3,5) 
  4007.  
  4008.             select @failover_mode_id = 0
  4009.         end
  4010.     end
  4011.  
  4012.     --
  4013.     -- prepare the output
  4014.     --
  4015.     select @failover_mode = case 
  4016.         when @failover_mode_id = 0 then N'immediate'
  4017.         when @failover_mode_id = 1 then N'queued'
  4018.         end
  4019.         
  4020.     select N'failover_mode value'  = @failover_mode_id, 
  4021.             N'failover_mode' = @failover_mode
  4022.  
  4023.     --
  4024.     -- all done
  4025.     --
  4026.     return 0
  4027. END
  4028. go
  4029. exec dbo.sp_MS_marksystemobject sp_helpreplfailovermode
  4030. go
  4031. grant execute on dbo.sp_helpreplfailovermode to public
  4032. go
  4033.  
  4034. --------------------------------------------------------------------------------
  4035. --. sp_setreplfailovermode
  4036. --------------------------------------------------------------------------------
  4037.  
  4038. if exists (select * from sysobjects
  4039.     where type = 'P' and name = 'sp_setreplfailovermode')
  4040. drop procedure sp_setreplfailovermode
  4041. go
  4042. raiserror('Creating procedure sp_setreplfailovermode', 0,1)
  4043. go
  4044. create procedure sp_setreplfailovermode (
  4045.     @publisher sysname,
  4046.     @publisher_db sysname,
  4047.     @publication sysname,
  4048.     @failover_mode nvarchar (10), 
  4049.     @override tinyint = 0)
  4050. as
  4051. begin
  4052.     set nocount on
  4053.     declare    @failover_mode_id tinyint, 
  4054.             @current_failover_mode_id bit,
  4055.             @retcode int,
  4056.             @queue_id sysname,
  4057.             @fqueue_empty int,
  4058.             @update_mode int,
  4059.             @queue_server sysname
  4060.  
  4061.     --
  4062.     -- security check
  4063.     --
  4064.     exec @retcode = sp_MSreplcheck_subscribe
  4065.     if @@error <> 0 or @retcode <> 0
  4066.     begin
  4067.         return (1)
  4068.     end
  4069.     --
  4070.     -- validate @failover_mode
  4071.     --
  4072.     if @failover_mode not in (N'immediate', N'sync', N'queued')
  4073.     begin
  4074.         raiserror (21184, 16, 1, '@failover_mode', 'immediate', 'sync', 'queued')
  4075.         return 1            
  4076.     end
  4077.     else
  4078.     begin
  4079.         if @failover_mode = 'immediate' or @failover_mode = 'sync'
  4080.             select @failover_mode_id = 0
  4081.         else if @failover_mode = 'queued'
  4082.             select @failover_mode_id = 1
  4083.     end
  4084.  
  4085.     --
  4086.     -- Only valid to get/set failover_mode, 
  4087.     -- if update_mode is failover (3,5)
  4088.     --
  4089.     select    @queue_id = queue_id, 
  4090.             @queue_server = queue_server,
  4091.             @current_failover_mode_id = failover_mode,
  4092.             @update_mode = update_mode
  4093.     from MSsubscription_agents
  4094.     where UPPER(publisher) = UPPER(@publisher) and 
  4095.         publisher_db = @publisher_db and
  4096.         publication = @publication and
  4097.         update_mode in (3,5)
  4098.  
  4099.     -- no such row exists
  4100.     if (@current_failover_mode_id is NULL)        
  4101.     begin
  4102.         raiserror (21185, 16, 1)
  4103.         return 1
  4104.     end
  4105.  
  4106.     -- should have a queue entry
  4107.     if (@queue_id is NULL)
  4108.     begin
  4109.         raiserror(21186, 16, 1, @publisher)
  4110.         return 1
  4111.     end
  4112.  
  4113.     --
  4114.     -- do the transition
  4115.     --
  4116.     if ((@current_failover_mode_id = 0 and @failover_mode_id = 0) or
  4117.             (@current_failover_mode_id = 1 and @failover_mode_id = 1))
  4118.     begin
  4119.         --
  4120.         -- Going from immediate to immediate, queued to queued is no-op
  4121.         --
  4122.         raiserror (21187, 16, 1)
  4123.     end
  4124.     else if (@current_failover_mode_id = 0 and @failover_mode_id = 1)
  4125.     begin
  4126.         --
  4127.         -- Going from immediate to queued : update MSsubscription_agents
  4128.         --
  4129.         update MSsubscription_agents
  4130.             set failover_mode = @failover_mode_id
  4131.             where UPPER(publisher) = UPPER(@publisher) and 
  4132.                 publisher_db = @publisher_db and
  4133.                 publication = @publication and
  4134.                 update_mode in (3,5)
  4135.  
  4136.         raiserror (21188, 10, 1, 'immediate', 'queued')
  4137.     end
  4138.     else if (@current_failover_mode_id = 1 and @failover_mode_id = 0)
  4139.     begin
  4140.         --
  4141.         -- Going from queued to immediate : if override is not set
  4142.         -- then check if the queue is empty and then allow if empty.
  4143.         -- If override is set, just update MSsubscription_agents
  4144.         --
  4145.         if (@override = 0)
  4146.         begin
  4147.             if (@update_mode = 3)
  4148.             begin
  4149.                 --
  4150.                 -- MSMQ processing
  4151.                 -- prefix the queue_id with queue server in direct format
  4152.                 -- and then perform peek in the queue
  4153.                 --
  4154.                 select @queue_id = N'DIRECT=OS:' + @queue_server + N'\PRIVATE$\' + @queue_id
  4155.                 
  4156.                 exec @retcode = master.dbo.xp_peekqueue @queue_id, @fqueue_empty output, 0
  4157.                 if (@@error != 0 or @retcode != 0)
  4158.                 begin
  4159.                     raiserror('sp_setreplfailovermode(debug): xp_peekqueue execution failed', 16, 1)
  4160.                     return 1
  4161.                 end
  4162.  
  4163.                 if (@fqueue_empty != 1)
  4164.                 begin
  4165.                     raiserror(21189, 16, 1, @queue_id)
  4166.                     return 1
  4167.                 end
  4168.             end
  4169.             else
  4170.             begin
  4171.                 --
  4172.                 -- SQL Queue processing
  4173.                 --
  4174.                 if exists (select * from MSreplication_queue 
  4175.                     where UPPER(publisher) = UPPER(@publisher) and 
  4176.                             publisher_db = @publisher_db and
  4177.                             publication = @publication )
  4178.                 begin
  4179.                     raiserror(21189, 16, 2, @queue_id)
  4180.                     return 1
  4181.                 end
  4182.             end
  4183.         end
  4184.         else
  4185.         begin
  4186.             raiserror(21190, 10, 1, 'queued', 'immediate')
  4187.         end
  4188.  
  4189.         --
  4190.         -- update MSsubscription_agents
  4191.         --
  4192.         update MSsubscription_agents
  4193.             set failover_mode = @failover_mode_id
  4194.             where publisher = @publisher and 
  4195.                 publisher_db = @publisher_db and
  4196.                 publication = @publication and
  4197.                 update_mode in (3,5)
  4198.  
  4199.         raiserror (21188, 10, 1, 'queued', 'immediate')
  4200.     end
  4201.  
  4202.     -- All done
  4203.     return 0
  4204. end
  4205. go
  4206. exec dbo.sp_MS_marksystemobject sp_setreplfailovermode
  4207. go
  4208. grant execute on dbo.sp_helpreplfailovermode to public
  4209. go
  4210.  
  4211. --------------------------------------------------------------------------------
  4212. --. sp_addqueued_artinfo
  4213. --------------------------------------------------------------------------------
  4214.  
  4215. if exists (select * from sysobjects
  4216.     where type = 'P' and name = 'sp_addqueued_artinfo')
  4217. drop procedure sp_addqueued_artinfo
  4218. go
  4219. raiserror('Creating procedure sp_addqueued_artinfo', 0,1)
  4220. go
  4221. CREATE PROCEDURE sp_addqueued_artinfo (
  4222.     @artid                int
  4223.     ,@article            sysname
  4224.     ,@publisher         sysname
  4225.     ,@publisher_db        sysname
  4226.     ,@publication        sysname
  4227.     ,@dest_table        sysname
  4228.     ,@owner                sysname
  4229.     ,@cft_table            sysname
  4230.     ,@columns            binary(32))
  4231. AS
  4232. BEGIN
  4233.     set nocount on
  4234.     declare     @agent_id int
  4235.                 ,@update_mode int
  4236.                 ,@retcode int
  4237.  
  4238.     --
  4239.     -- security check
  4240.     --
  4241.     exec @retcode = sp_MSreplcheck_subscribe
  4242.     if @@error <> 0 or @retcode <> 0
  4243.     begin
  4244.         return (1)
  4245.     end
  4246.     --
  4247.     -- Create system table MSsubscription_articles if it does not exist
  4248.     --
  4249.     IF NOT EXISTS (SELECT * FROM sysobjects WHERE 
  4250.         type = 'U' AND name = 'MSsubscription_articles')
  4251.     BEGIN
  4252.         CREATE TABLE dbo.MSsubscription_articles
  4253.         (
  4254.             agent_id        int NOT NULL,        -- related entry in MSsubscription_agents
  4255.             artid            int NOT NULL,        -- article id
  4256.             article            sysname,            -- article name
  4257.             dest_table        sysname,            -- destination table
  4258.             owner            sysname,
  4259.             cft_table        sysname,            -- conflict table
  4260.             columns            binary(32)
  4261.         )
  4262.         IF (@@ERROR != 0)
  4263.         begin
  4264.             raiserror('Debug:sp_addqueued_artinfo - create MSsubscription_articles failed', 16, 1)
  4265.             return (1)
  4266.         end
  4267.  
  4268.         CREATE UNIQUE CLUSTERED INDEX ucMSsubscription_articles ON dbo.MSsubscription_articles(agent_id, artid)
  4269.         IF (@@ERROR != 0)
  4270.         begin
  4271.             raiserror('Debug:sp_addqueued_artinfo - create index for MSsubscription_articles failed', 16, 1)
  4272.             return (1)
  4273.         end
  4274.         
  4275.         EXEC dbo.sp_MS_marksystemobject 'MSsubscription_articles'
  4276.     END
  4277.  
  4278.     --
  4279.     -- insert the row for the given article
  4280.     --
  4281.     select @agent_id = id, @update_mode = update_mode
  4282.     from MSsubscription_agents 
  4283.     where UPPER(publisher) = UPPER(@publisher) and 
  4284.         publisher_db = @publisher_db and 
  4285.         publication = @publication 
  4286.  
  4287.     if (@agent_id IS NULL)
  4288.     begin
  4289.         raiserror('Debug:sp_addqueued_artinfo - agent_id is null for [%s].[%s].[%s]', 
  4290.             16, 1, @publisher, @publisher_db, @publication)
  4291.         return (1)
  4292.     end
  4293.  
  4294.     -- If the subscription is read only or immediate, no need to article info.
  4295.     if @update_mode in (0,1)
  4296.         return 0
  4297.  
  4298.     --
  4299.     -- If MSMQ Queued mode - check if the subscriber is compliant for MSMQ 2.0
  4300.     --
  4301.     if (@update_mode in (2,3))
  4302.     begin
  4303.         if ((platform() & 0x1) != 0x1)
  4304.         begin
  4305.             --
  4306.             -- Win 9X platform
  4307.             --
  4308.             raiserror(21334, 16, 1, '2.0')
  4309.             return (1)
  4310.         end
  4311.  
  4312.         --
  4313.         -- Now we use xp_MSver to detect NT OS version
  4314.         -- MSMQ subscription only allowed for platforms that support MSMQ 2.0
  4315.         -- version 5.0.2195 or higher
  4316.         --
  4317.         create table #tosversion ( propid int, propname sysname collate database_default, value int, charvalue nvarchar(255) collate database_default)
  4318.         insert into #tosversion (propid, propname, value, charvalue)
  4319.             exec master.dbo.xp_msver N'WindowsVersion'
  4320.  
  4321.         declare @vervalue int
  4322.             ,@lobyte tinyint
  4323.             ,@hibyte tinyint
  4324.             ,@loword smallint
  4325.             ,@hiword smallint
  4326.  
  4327.         --
  4328.         -- low order byte of low order word = OSmajor, high order byte of low order word = OSminor
  4329.         -- high order word = OSbuild
  4330.         --
  4331.         select @vervalue = value from #tosversion where propname = N'WindowsVersion'
  4332.         select @loword = (@vervalue & 0xffff)
  4333.                 ,@hiword = (@vervalue / 0x10000) & 0xffff
  4334.         select @lobyte = @loword & 0xff
  4335.                 ,@hibyte = (@loword / 100) & 0xff
  4336.         drop table #tosversion
  4337.  
  4338.         --
  4339.         -- check for OS major version
  4340.         --
  4341.         if (@lobyte < 5)
  4342.         begin
  4343.             raiserror(21334, 16, 2, '2.0')
  4344.             return (1)
  4345.         end
  4346.  
  4347.         --
  4348.         -- check for OS build version
  4349.         --
  4350.         if (@lobyte = 5 and @hiword < 2195)
  4351.         begin
  4352.             raiserror(21334, 16, 3, '2.0')
  4353.             return (1)
  4354.         end
  4355.     end
  4356.  
  4357.     --
  4358.     -- Check for owner - use current user for NULL value
  4359.     --
  4360.     if (@owner IS NULL or lower(@owner) = N'null' collate database_default)
  4361.         select @owner = user_name()
  4362.  
  4363.     if exists (select * from MSsubscription_articles where agent_id = @agent_id and artid = @artid)
  4364.         delete MSsubscription_articles where agent_id = @agent_id and artid = @artid
  4365.         
  4366.     insert into MSsubscription_articles(agent_id, artid, article, dest_table, owner, cft_table, columns)
  4367.         values (@agent_id, @artid, @article, @dest_table, @owner, @cft_table, @columns)
  4368.  
  4369.     IF (@@ERROR != 0)
  4370.     begin
  4371.         raiserror('Debug:sp_addqueued_artinfo - insert failed', 16, 1)
  4372.         return (1)
  4373.     end
  4374.  
  4375.     --
  4376.     -- Do the queue initialization here
  4377.     -- this way we can initialize Snapshot/Logbased queued tran from one place
  4378.     --
  4379.     exec @retcode = dbo.sp_MSreset_queue @publisher, @publisher_db, @publication, @artid
  4380.     IF (@retcode != 0 or @@ERROR != 0)
  4381.     begin
  4382.         raiserror('Debug:sp_addqueued_artinfo - sp_MSreset_queue failed', 16, 1)
  4383.         return (1)
  4384.     end
  4385.     
  4386.     --
  4387.     -- all done
  4388.     --
  4389.     return 0    
  4390. END
  4391. go
  4392. exec dbo.sp_MS_marksystemobject sp_addqueued_artinfo
  4393. go
  4394. grant execute on dbo.sp_addqueued_artinfo to public
  4395. go
  4396.  
  4397. --------------------------------------------------------------------------------
  4398. --. sp_MSreset_queued_reinit
  4399. --------------------------------------------------------------------------------
  4400.  
  4401. if exists (select * from sysobjects
  4402.     where type = 'P' and name = 'sp_MSreset_queued_reinit')
  4403. drop procedure sp_MSreset_queued_reinit
  4404. go
  4405. raiserror('Creating procedure sp_MSreset_queued_reinit', 0,1)
  4406. go
  4407. create procedure sp_MSreset_queued_reinit (
  4408.     @subscriber      sysname,                    -- subscriber server name
  4409.     @subscriber_db   sysname,                    -- subscribing database name. 
  4410.     @artid    int)                                   -- article id
  4411. as
  4412. begin
  4413.     set nocount on
  4414.     declare @srvid int
  4415.         ,@retcode int
  4416.         ,@publication sysname
  4417.     --
  4418.     -- PAL security check
  4419.     -- Get publication name using artid
  4420.     --
  4421.     select @publication = p.name
  4422.     from syspublications p join sysarticles a on p.pubid = a.pubid
  4423.     where a.artid = @artid
  4424.     if (@publication is null)
  4425.     begin
  4426.         return 1
  4427.     end
  4428.     exec @retcode = dbo.sp_MSreplcheck_pull @publication = @publication
  4429.     if @@error <> 0 or @retcode <> 0
  4430.     begin
  4431.         return (1)
  4432.     end
  4433.     select @srvid = srvid from master.dbo.sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  4434.     --
  4435.     -- set the reinit flag
  4436.     --
  4437.     update dbo.syssubscriptions
  4438.     set queued_reinit = 0
  4439.     where 
  4440.         artid = @artid 
  4441.         and srvid = @srvid
  4442.         and dest_db = @subscriber_db
  4443.     if (@@error != 0)
  4444.         return 1
  4445.  
  4446.     -- all done
  4447.     return 0
  4448. end
  4449. go
  4450. exec dbo.sp_MS_marksystemobject sp_MSreset_queued_reinit
  4451. go
  4452. grant execute on dbo.sp_MSreset_queued_reinit to public
  4453. go
  4454. --------------------------------------------------------------------------------
  4455. --. fn_escapecmdshellsymbols
  4456. --------------------------------------------------------------------------------
  4457. if exists (select * from sysobjects
  4458.     where type = 'FN'
  4459.     and name = N'fn_escapecmdshellsymbols' )
  4460. drop function system_function_schema.fn_escapecmdshellsymbols
  4461. go
  4462. raiserror('Creating function fn_escapecmdshellsymbols', 0,1) with nowait
  4463. go
  4464. --
  4465. -- Name: fn_escapecmdshellsymbols
  4466. --
  4467. -- Descriptions: This function returns an escaped version of a given string
  4468. --               with carets ('^') added in front of all the special 
  4469. --               command shell symbols. In the W2K online help (Start->
  4470. --               Help->Index->Command Reference->Command Symbols...), the 
  4471. --               following symbols are listed as special command symbols:
  4472. --                 (N'%', N'<', N'>', N'|', N'&', N'(', N')', N'^', N'"')
  4473. --
  4474. -- Parameter: @command_string nvarchar(4000)
  4475. -- 
  4476. -- Example: select fn_escapecmdshellsymbols(N'The % quick < brown > dog | jumps & over ( the ) lazy ^ fox.') 
  4477. --             will return 
  4478. --    
  4479. --    The ^% quick ^< brown ^> dog ^| jumps ^& over ^( the ^) lazy ^^ fox
  4480. --
  4481. -- Security: This function is granted to public
  4482. --
  4483. create function system_function_schema.fn_escapecmdshellsymbols(
  4484.     @command_string nvarchar(4000)
  4485.     ) returns nvarchar(4000)
  4486. as
  4487. begin
  4488.     declare @escaped_command_string nvarchar(4000),
  4489.             @curr_char nvarchar(1),
  4490.             @curr_char_index int    
  4491.     select @escaped_command_string = N'',
  4492.            @curr_char = N'', 
  4493.            @curr_char_index = 1
  4494.     while @curr_char_index <= len(@command_string)
  4495.     begin
  4496.         select @curr_char = substring(@command_string, @curr_char_index, 1) 
  4497.         if @curr_char in (N'%', N'<', N'>', N'|', N'&', N'(', N')', N'^', N'"')
  4498.         begin
  4499.             select @escaped_command_string = @escaped_command_string + N'^'
  4500.         end
  4501.         select @escaped_command_string = @escaped_command_string + @curr_char
  4502.         select @curr_char_index = @curr_char_index + 1 
  4503.     end
  4504.     return @escaped_command_string
  4505. end
  4506. go
  4507. grant execute on system_function_schema.fn_escapecmdshellsymbols to public
  4508.  
  4509. --------------------------------------------------------------------------------
  4510. --. fn_escapecmdshellsymbolsremovequotes
  4511. --------------------------------------------------------------------------------
  4512. if exists (select * from sysobjects
  4513.     where type = 'FN'
  4514.     and name = N'fn_escapecmdshellsymbolsremovequotes' )
  4515.     drop function system_function_schema.fn_escapecmdshellsymbolsremovequotes
  4516.  
  4517. raiserror('Creating function fn_escapecmdshellsymbolsremovequotes', 0,1) with nowait
  4518. go
  4519. --
  4520. -- Name: fn_escapecmdshellsymbolsremovequotes
  4521. --
  4522. -- Descriptions: The only difference between this function and 
  4523. --               fn_escapecmdshellsymbols is that "'s are removed from the 
  4524. --               resulting command line.
  4525. --
  4526. -- Parameter: @command_string nvarchar(4000)
  4527. -- 
  4528. -- Security: This function is granted to public
  4529. --
  4530. create function system_function_schema.fn_escapecmdshellsymbolsremovequotes(
  4531.     @command_string nvarchar(4000)
  4532.     ) returns nvarchar(4000)
  4533. as
  4534. begin
  4535.     declare @escaped_command_string nvarchar(4000),
  4536.             @curr_char nvarchar(1),
  4537.             @curr_char_index int    
  4538.     select @escaped_command_string = N'',
  4539.            @curr_char = N'', 
  4540.            @curr_char_index = 1
  4541.     while @curr_char_index <= len(@command_string)
  4542.     begin
  4543.         select @curr_char = substring(@command_string, @curr_char_index, 1) 
  4544.         if @curr_char in (N'%', N'<', N'>', N'|', N'&', N'(', N')', N'^')
  4545.         begin
  4546.             select @escaped_command_string = @escaped_command_string + N'^'
  4547.         end
  4548.         if @curr_char <> '"'
  4549.         begin
  4550.             select @escaped_command_string = @escaped_command_string + @curr_char
  4551.         end
  4552.         select @curr_char_index = @curr_char_index + 1 
  4553.     end
  4554.     return @escaped_command_string
  4555. end
  4556. go
  4557. grant execute on system_function_schema.fn_escapecmdshellsymbolsremovequotes to public
  4558.  
  4559. --------------------------------------------------------------------------------
  4560. --. sp_MSget_file_existence
  4561. --------------------------------------------------------------------------------
  4562. if exists (select * from sysobjects
  4563.     where type = 'P' and name = 'sp_MSget_file_existence')
  4564. drop procedure sp_MSget_file_existence
  4565. go
  4566. print ''
  4567. print 'Creating procedure sp_MSget_file_existence'
  4568. go
  4569. create procedure sp_MSget_file_existence (
  4570. @filename nvarchar(260),
  4571. @exists bit = 0 output
  4572. )
  4573. AS
  4574.     SET NOCOUNT ON
  4575.  
  4576.     DECLARE @command nvarchar(512)
  4577.     DECLARE @retcode int
  4578.     declare @echo_text nvarchar(20)
  4579.  
  4580.     select @echo_text = 'file_exists'
  4581.  
  4582.     /*
  4583.     ** The return code from xp_cmdshell is not a reliable way to check whether the file exists or
  4584.     ** not. It is always 0 on Win95 as long as xp_cmdshell succeeds.
  4585.     */  
  4586.  
  4587.     select @command = N'if exist "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + N'" echo ' + @echo_text
  4588.  
  4589.     create table #text_ret(cmdoutput nvarchar(20) collate database_default null)
  4590.  
  4591.     insert into #text_ret exec @retcode = master..xp_cmdshell @command
  4592.     if @@error <> 0 or @retcode <> 0
  4593.         return 1
  4594.  
  4595.     if exists (select * from #text_ret where ltrim(rtrim(cmdoutput)) = @echo_text)
  4596.         select @exists = 1
  4597.     else 
  4598.         select @exists = 0
  4599.  
  4600.     drop table #text_ret
  4601. go
  4602. EXEC dbo.sp_MS_marksystemobject sp_MSget_file_existence
  4603. GO
  4604.  
  4605. --------------------------------------------------------------------------------
  4606. --. sp_replicationoption
  4607. --------------------------------------------------------------------------------
  4608. if exists (select * from sysobjects
  4609.     where type = 'P' and name = 'sp_replicationoption')
  4610. drop procedure sp_replicationoption
  4611. go
  4612. raiserror('Creating procedure sp_replicationoption', 0,1)
  4613. go
  4614.  
  4615. CREATE PROCEDURE sp_replicationoption (
  4616. @optname        sysname,
  4617. @value            nvarchar(5),
  4618. @security_mode    int = 0,
  4619. @login            sysname = 'sa',
  4620. @password        sysname = NULL,
  4621. @reserved       nvarchar(20) = NULL
  4622. )
  4623. AS
  4624.     DECLARE @optbit bit
  4625.     DECLARE @osql_path nvarchar(260)
  4626.     DECLARE @osql_cmd1 nvarchar (255)
  4627.     DECLARE @osql_cmd_full nvarchar (255)
  4628.     DECLARE @osql_for_nt int
  4629.  
  4630.     DECLARE @install_path nvarchar (255)
  4631.  
  4632.     DECLARE @retcode int
  4633.     DECLARE @undo_install nvarchar(20)
  4634.     DECLARE @no_scripts nvarchar(10)
  4635.     DECLARE @platform_nt binary
  4636.     
  4637.     SELECT @platform_nt = 0x1
  4638.  
  4639.     if    is_srvrolemember('sysadmin') <> 1
  4640.         BEGIN
  4641.             RAISERROR (15232, 14, -1)
  4642.             RETURN (1)
  4643.         END
  4644.     
  4645.     SELECT @no_scripts = 'no_scripts'
  4646.  
  4647.     SELECT @undo_install = 'undo_install'
  4648.  
  4649.     IF db_name() <> 'master'
  4650.     BEGIN
  4651.         RAISERROR(5001, 16,-1)
  4652.         GOTO FAILURE
  4653.     END
  4654.  
  4655.     IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('transactional','merge')
  4656.     BEGIN
  4657.         RAISERROR(21014, 16, -1)
  4658.         GOTO FAILURE
  4659.     END
  4660.     IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true','false')
  4661.     BEGIN
  4662.         RAISERROR(14137,16,-1)
  4663.         GOTO FAILURE
  4664.     END
  4665.     
  4666.     IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  4667.         SELECT @optbit = 1
  4668.     ELSE
  4669.         SELECT @optbit = 0
  4670.  
  4671.     /*
  4672.     ** Check if the option is set as required already
  4673.     */
  4674.     IF @reserved <> @undo_install AND EXISTS (SELECT * FROM MSreplication_options
  4675.         WHERE    optname  = @optname
  4676.         AND        value = @optbit)
  4677.     BEGIN
  4678.         IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  4679.             RAISERROR (21015, 10, -1, @optname)        
  4680.         ELSE
  4681.             RAISERROR (21016, 10, -1, @optname)
  4682.         GOTO FAILURE
  4683.     END
  4684.  
  4685.     /* Install replication */
  4686.     IF @optbit = 1
  4687.     BEGIN
  4688.  
  4689.         IF LOWER(@reserved collate SQL_Latin1_General_CP1_CS_AS) = @no_scripts
  4690.             GOTO NO_SCRIPTS
  4691.  
  4692.         -- Set the flag for platform
  4693.         IF (( platform() & @platform_nt = @platform_nt ))
  4694.             SELECT @osql_for_nt = 1
  4695.         ELSE
  4696.             SELECT @osql_for_nt = 0
  4697.  
  4698.         /* 
  4699.         ** Get installation path -- osql client (TOOLS) path
  4700.         */
  4701.         EXECUTE @retcode = master.dbo.sp_MSgettools_path @osql_path OUTPUT
  4702.         IF ( @@ERROR <> 0 ) OR ( @retcode <> 0 ) or ( @osql_path is NULL ) or ( @osql_path = '' )
  4703.         BEGIN
  4704.             GOTO FAILURE       
  4705.         END
  4706.  
  4707.         /* 
  4708.         ** Get installation path -- instance specific (INSTALL) directory
  4709.         */
  4710.         exec @retcode = master.dbo.sp_MSget_setup_paths
  4711.             @sql_path = @install_path output
  4712.         IF @@ERROR<> 0 OR @retcode <> 0 or @install_path is NULL or @install_path=''
  4713.             BEGIN
  4714.                 GOTO FAILURE       
  4715.             END
  4716.  
  4717.         /* 
  4718.         ** Install replcom.sql and repltran.sql
  4719.         */
  4720.         IF @security_mode = 1
  4721.         begin
  4722.             SELECT @osql_cmd1 = '"' + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -E ' 
  4723.             if serverproperty('instancename') is not null
  4724.                 SELECT @osql_cmd1 = @osql_cmd1 + ' -S"' + @@SERVERNAME + '" '
  4725.         end
  4726.         ELSE
  4727.             -- cannot specify -S w/ -E for local execution, SID does not map
  4728.             SELECT @osql_cmd1 = '"' + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -U"' + fn_escapecmdshellsymbols(@login) collate database_default + '" -P"' + 
  4729.                 fn_escapecmdshellsymbols(isnull(@password,'')) collate database_default + '" -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" '
  4730.  
  4731.         select @osql_cmd1 = @osql_cmd1 + '-l30 -t30 '
  4732.  
  4733.         -- Install replcom.sql 
  4734.         -- Only apply replcom.sql if it was not applied before.
  4735.         -- '-b' option will make osql stop at errors and return error code
  4736.         -- We must use this option.
  4737.         IF NOT EXISTS (SELECT * FROM MSreplication_options
  4738.             WHERE value = 1)
  4739.         BEGIN
  4740.             -- Initialize the Command
  4741.             IF (@osql_for_nt = 1)
  4742.                 SELECT @osql_cmd_full = '" '
  4743.             ELSE
  4744.                 SELECT @osql_cmd_full = ' '
  4745.  
  4746.             SELECT @osql_cmd_full = @osql_cmd_full +
  4747.                 @osql_cmd1 + 
  4748.                 ' -dmaster' +  ' -b ' +
  4749.                 ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\replcom.sql"' + 
  4750.                 ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\replcom.out"' 
  4751.  
  4752.             IF (@osql_for_nt = 1)
  4753.                 SELECT @osql_cmd_full = @osql_cmd_full + ' "'
  4754.  
  4755.             EXEC @retcode = master..xp_cmdshell @osql_cmd_full
  4756.             IF @@ERROR<> 0 OR @retcode <> 0
  4757.             BEGIN
  4758.                 RAISERROR (14113, 16, -1, @osql_cmd_full, 'replcom.out')
  4759.                 GOTO UNDO_INSTALL     
  4760.             END
  4761.         END
  4762.  
  4763.         IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'transactional'
  4764.         BEGIN
  4765.             -- Install repltran.sql
  4766.             IF (@osql_for_nt = 1)
  4767.                 SELECT @osql_cmd_full = '" '
  4768.             ELSE
  4769.                 SELECT @osql_cmd_full = ' '
  4770.  
  4771.             SELECT @osql_cmd_full = @osql_cmd_full +
  4772.                 @osql_cmd1 + 
  4773.                 ' -dmaster' +  ' -b ' +
  4774.                 ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\repltran.sql"' + 
  4775.                 ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\repltran.out"' 
  4776.  
  4777.             IF (@osql_for_nt = 1)
  4778.                 SELECT @osql_cmd_full = @osql_cmd_full + ' "'
  4779.  
  4780.             EXEC @retcode = master..xp_cmdshell @osql_cmd_full
  4781.             IF @@ERROR<> 0 OR @retcode <> 0
  4782.             BEGIN
  4783.                 RAISERROR (14113, 16, -1, @osql_cmd_full, 'repltran.out')
  4784.                 GOTO UNDO_INSTALL     
  4785.             END
  4786.  
  4787.         END
  4788.  
  4789.         IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'merge'
  4790.         BEGIN
  4791.             -- Install replmerg.sql 
  4792.             IF (@osql_for_nt = 1)
  4793.                 SELECT @osql_cmd_full = '" '
  4794.             ELSE
  4795.                 SELECT @osql_cmd_full = ' '
  4796.  
  4797.             SELECT @osql_cmd_full = @osql_cmd_full +
  4798.                 @osql_cmd1 + 
  4799.                 ' -dmaster' + ' -b ' +
  4800.                 ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\replmerg.sql"' + 
  4801.                 ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\replmerg.out"' 
  4802.             
  4803.             IF (@osql_for_nt = 1)
  4804.                 SELECT @osql_cmd_full = @osql_cmd_full + ' "'
  4805.  
  4806.             EXEC @retcode = master..xp_cmdshell @osql_cmd_full 
  4807.             
  4808.             IF  @@ERROR<> 0 OR @retcode <> 0
  4809.             BEGIN
  4810.                 RAISERROR (14113, 16, -1, @osql_cmd_full, 'replmerg.out')
  4811.                 GOTO UNDO_INSTALL     
  4812.             END
  4813.         END
  4814.  
  4815. NO_SCRIPTS:
  4816.  
  4817.         UPDATE MSreplication_options SET value = @optbit
  4818.             WHERE optname = @optname
  4819.         IF @@ERROR <> 0 
  4820.         BEGIN
  4821.             GOTO UNDO_INSTALL    
  4822.         END
  4823.  
  4824.     END
  4825.     /* Uninstall replication */
  4826.     ELSE
  4827.     BEGIN
  4828.  
  4829.         /* 
  4830.         ** Make sure no distributor installed before dropping 
  4831.         ** replication stored procedures
  4832.         */
  4833.         IF EXISTS (SELECT * FROM master..sysservers
  4834.               WHERE  srvstatus & 8 <> 0)
  4835.         BEGIN
  4836.             RAISERROR (21021, 16, -1)
  4837.             RETURN(1)
  4838.         END
  4839.  
  4840.         UPDATE MSreplication_options SET value = @optbit
  4841.             WHERE optname = @optname
  4842.         IF @@ERROR <> 0 
  4843.         BEGIN
  4844.             GOTO FAILURE
  4845.         END
  4846.  
  4847.         /* 
  4848.         *********** Do not drop replication stored procs anymore.
  4849.  
  4850.         IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'transactional'
  4851.         BEGIN
  4852.             if exists (select * from sysobjects
  4853.                 where type = 'P '
  4854.                         and name = 'sp_MSdrop_repltran')
  4855.             begin
  4856.                 exec @retcode = dbo.sp_MSdrop_repltran
  4857.                 if @@ERROR = 0 and @retcode = 0
  4858.                     drop procedure sp_MSdrop_repltran
  4859.             end
  4860.         END
  4861.  
  4862.         IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'merge'
  4863.         BEGIN
  4864.             if exists (select * from sysobjects
  4865.                 where type = 'P '
  4866.                         and name = 'sp_MSdrop_replmerg')
  4867.             begin
  4868.                 exec @retcode = dbo.sp_MSdrop_replmerg
  4869.                 if @@ERROR = 0 and @retcode = 0
  4870.                     drop procedure sp_MSdrop_replmerg
  4871.             end
  4872.         END
  4873.  
  4874.         IF NOT EXISTS (SELECT * FROM MSreplication_options
  4875.             WHERE value = 1)
  4876.         BEGIN
  4877.             if exists (select * from sysobjects
  4878.                 where type = 'P '
  4879.                         and name = 'sp_MSdrop_replcom')
  4880.             begin
  4881.                 exec @retcode = dbo.sp_MSdrop_replcom
  4882.                 if @@ERROR = 0 and @retcode = 0
  4883.                     drop procedure sp_MSdrop_replcom
  4884.             end
  4885.         END
  4886.  
  4887.         */
  4888.     END
  4889.  
  4890.     RETURN(0)
  4891.  
  4892. UNDO_INSTALL:
  4893.     /* This is needed to drop the stored procedures that were created. */
  4894.     EXEC dbo.sp_replicationoption @optname =  @optname, 
  4895.         @value = 'false', @reserved = @undo_install
  4896.  
  4897. FAILURE:
  4898.     RETURN(1)
  4899. GO
  4900. exec dbo.sp_MS_marksystemobject sp_replicationoption
  4901. go
  4902. grant execute on dbo.sp_replicationoption to public
  4903. go
  4904.  
  4905. --------------------------------------------------------------------------------
  4906. --. sp_vupgrade_replication
  4907. --------------------------------------------------------------------------------
  4908. if exists (select * from sysobjects
  4909.     where type = 'P' and name = 'sp_vupgrade_replication')
  4910. drop procedure sp_vupgrade_replication
  4911. go
  4912. raiserror('Creating procedure sp_vupgrade_replication', 0,1)
  4913. GO
  4914.  
  4915. create procedure sp_vupgrade_replication ( @login sysname = N'sa', @password sysname = N'', @ver_old int = 517, @force_remove tinyint = 0, @security_mode bit = 0 )
  4916. as
  4917. begin
  4918. /* 
  4919.  * Dispatcher proc for handling schema and metadata changes during setup initiated version upgrade 
  4920.  * for replication components. Any schema changes to replication system tables may require modifications 
  4921.  * here to maintain upgrade path. All modifications called in these procs are within "if exists" checks
  4922.  * making them repeatable for debugging and to support incremental upgrades (e.g. Beta 1 to Beta 2 to RTM)
  4923.  * 
  4924.  * If server is a distributor, run new instdist.sql against all distribution dbs.
  4925.  *
  4926.  * This proc gets called by setup at the end of an install over an existing version.
  4927. */
  4928.  
  4929.     set nocount on 
  4930.  
  4931.     declare @dbname sysname
  4932.     declare @has_dbaccess bit
  4933.     declare @install_path nvarchar(255)
  4934.     declare @osql_path nvarchar(260)
  4935.     declare @osql_cmd nvarchar(512)
  4936.     declare @osql_for_nt int
  4937.     declare @retcode int
  4938.     declare @platform_nt binary
  4939.     declare @db_distbit int
  4940.     declare @ver_min            int
  4941.     declare @ver_retention    int 
  4942.  
  4943.     select @db_distbit = 16
  4944.     select @platform_nt = 0x1
  4945.     select @ver_retention = 576 --build # on 9/17
  4946.  
  4947.     -- raiserror('sp_vupgrade_replication', 0,1) with nowait
  4948.  
  4949.     /*
  4950.      * obsolete check; ver check was to prevent repl upgrade from
  4951.      * versions prior to SQL7.0 Beta 3; check is removed by setting @ver_min = -1
  4952.     */
  4953.     select @ver_min= -1 -- change if later wish to support a minimum upgrade version
  4954.     if ( @ver_old < @ver_min ) or ( @force_remove = 1 )
  4955.         exec dbo.sp_removesrvreplication
  4956.     else
  4957.     begin
  4958.  
  4959.         /* 
  4960.          * always need to run instdist.sql to update distribution databases on a distributor
  4961.          * setup must restart in non-single user mode so we can shell out to run instdist.sql scripts
  4962.         */
  4963.         if exists( select * from master..sysdatabases where category & @db_distbit = @db_distbit )
  4964.         begin
  4965.  
  4966.             /* 
  4967.             ** Get installation path -- osql client (TOOLS) path
  4968.             */
  4969.             EXECUTE @retcode = master.dbo.sp_MSgettools_path @osql_path OUTPUT
  4970.             IF ( @@ERROR <> 0 ) OR ( @retcode <> 0 ) or ( @osql_path is NULL ) or ( @osql_path = '' )
  4971.             BEGIN
  4972.                 RETURN (1)
  4973.             END
  4974.  
  4975.             /* 
  4976.             ** Get installation path -- instance specific (INSTALL) directory
  4977.             */
  4978.             exec @retcode = master.dbo.sp_MSget_setup_paths
  4979.                 @sql_path = @install_path output
  4980.             IF @@ERROR<> 0 OR @retcode <> 0 or @install_path is NULL or @install_path=N''
  4981.             BEGIN
  4982.                 RETURN (1)
  4983.             END
  4984.  
  4985.             -- Set the flag for platform
  4986.             if (( platform() & @platform_nt = @platform_nt ))
  4987.                 select @osql_for_nt = 1
  4988.             else
  4989.                 select @osql_for_nt = 0
  4990.  
  4991.             declare cur_distdb CURSOR LOCAL FAST_FORWARD for 
  4992.                 select name, has_dbaccess(name) from master..sysdatabases 
  4993.                     where category & @db_distbit = @db_distbit
  4994.                 for read only
  4995.             
  4996.             open cur_distdb
  4997.             fetch cur_distdb into @dbname, @has_dbaccess
  4998.             while ( @@fetch_status <> -1 )
  4999.             begin
  5000.  
  5001.                 -- if distribution database is available upgrade it; if offline error out
  5002.                 if ( @has_dbaccess = 1 )
  5003.                 begin
  5004.                     raiserror( 21374, 0, 1, @dbname) with nowait
  5005.  
  5006.                     /*
  5007.                      * Format osql cmd line appropriate for security mode and OS to run instdist.sql against
  5008.                      * each distribution database. Instdist.sql will recompile procs and will also do some
  5009.                      * schema and metadata upgrade of changed replication tables. Query timeout increased to
  5010.                      * make enough time for alter tables in instdist.sql run for upgrade to complete.
  5011.                     */
  5012.                     if ( @osql_for_nt = 1 )
  5013.                         select @osql_cmd = N'" "'
  5014.                     else
  5015.                         select @osql_cmd = N' "'
  5016.                     
  5017.                     -- Cannot specify -S w/ -E for local execution, SID does not map (nofix)
  5018.                     if ( @security_mode = 1 and @osql_for_nt = 1 )
  5019.                     begin
  5020.                         select @osql_cmd = @osql_cmd + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -E '
  5021.                         if serverproperty('instancename') is not null
  5022.                             select @osql_cmd = @osql_cmd + ' -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" '
  5023.                     end
  5024.                     else
  5025.                         select @osql_cmd = @osql_cmd + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -U' + fn_escapecmdshellsymbols(isnull(@login, N'sa')) collate database_default + ' -P' + fn_escapecmdshellsymbols(isnull(@password, N'')) collate database_default + ' -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" '
  5026.  
  5027.                     select @osql_cmd = @osql_cmd + ' -l30 -t120 '
  5028.                     select @osql_cmd = @osql_cmd + ' -b ' + ' -d' + fn_escapecmdshellsymbols(@dbname) collate database_default
  5029.                     select @osql_cmd = @osql_cmd +    ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\instdist.sql"' + 
  5030.                                                     ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\instdist.out"'            
  5031.  
  5032.                     if (@osql_for_nt = 1)
  5033.                         select @osql_cmd = @osql_cmd + ' "'
  5034.  
  5035.                      exec @retcode = master..xp_cmdshell @osql_cmd
  5036.                     if @retcode <> 0 or @@error <> 0
  5037.                     begin
  5038.                         raiserror (14113, 16, -1, @osql_cmd, 'instdist.out')
  5039.                     end
  5040.  
  5041.                     /*
  5042.                      * Process schema and metadata changes for each distribution database
  5043.                     */
  5044.  
  5045.                     select @dbname = quotename(@dbname)
  5046.                     exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_distdb')
  5047.                     if @@error <> 0
  5048.                         return(1)
  5049.                 end
  5050.                 else
  5051.                 begin
  5052.                     /* Report informational message stating distribution
  5053.                     ** database is not accessible.
  5054.                     */
  5055.                     raiserror( 21378, 10, 1, @dbname) with nowait
  5056.                 end
  5057.                 
  5058.                 fetch next from cur_distdb into @dbname, @has_dbaccess
  5059.             end
  5060.             close cur_distdb
  5061.             deallocate cur_distdb
  5062.         end
  5063.  
  5064.         -- vupgrade_publisher runs at 
  5065.         exec @retcode = dbo.sp_vupgrade_publisher 
  5066.             @ver_old = @ver_old, 
  5067.             @ver_retention = @ver_retention
  5068.         if @retcode<>0 or @@error<>0
  5069.             return (1)
  5070.     
  5071.         -- Update subscription database schema
  5072.         exec @retcode = dbo.sp_vupgrade_subscription_databases
  5073.         if @retcode <> 0 or @@error <> 0
  5074.             return (1)
  5075.  
  5076.  
  5077.     end
  5078.  
  5079.     return (0)
  5080.  
  5081. end
  5082. go
  5083.  
  5084. exec dbo.sp_MS_marksystemobject sp_vupgrade_replication
  5085. go
  5086.  
  5087. --------------------------------------------------------------------------------
  5088. --. sp_MScopysnapshot
  5089. --------------------------------------------------------------------------------
  5090. if exists (select * from sysobjects
  5091.     where type = 'P' and name = 'sp_MScopysnapshot')
  5092. drop procedure sp_MScopysnapshot
  5093. go
  5094. raiserror('Creating procedure sp_MScopysnapshot', 0,1)
  5095. go
  5096. CREATE PROCEDURE sp_MScopysnapshot (
  5097.     @source_folder           nvarchar(255),
  5098.     @destination_folder      nvarchar(255)
  5099.     )
  5100. AS
  5101. BEGIN
  5102.     SET NOCOUNT ON
  5103.     DECLARE @directory_exists bit    
  5104.     DECLARE @ftporuncdir      nvarchar(5)
  5105.     DECLARE @pubdir           nvarchar(255)
  5106.     DECLARE @timestampdir     nvarchar(255)
  5107.     DECLARE @bslashindex      int
  5108.     DECLARE @bslashindex2     int
  5109.     DECLARE @bslashcounter    int
  5110.     DECLARE @command          nvarchar(1000)
  5111.     DECLARE @retcode          int
  5112.     DECLARE @platform_nt      bit
  5113.  
  5114.     IF platform() & 0x1 = 0x1
  5115.         SELECT @platform_nt = 1
  5116.     ELSE
  5117.         SELECT @platform_nt = 0
  5118.  
  5119.     -- If @source_folder is NULL then either the snapshot has not been 
  5120.     -- generated or it has been cleaned up
  5121.     IF @source_folder IS NULL OR @source_folder = N''
  5122.     BEGIN
  5123.         RAISERROR(21289, 16, -1)
  5124.         RETURN (1)
  5125.     END
  5126.  
  5127.     -- Make sure that the @destination folder is not null
  5128.     IF @destination_folder IS NULL OR
  5129.        @destination_folder = N''
  5130.     BEGIN
  5131.         RAISERROR(21287, 16, -1)      
  5132.         RETURN (1)
  5133.     END
  5134.  
  5135.     -- Append backslash to @destination_folder if it is not 
  5136.     -- there already
  5137.     IF SUBSTRING(@destination_folder, LEN(@destination_folder), 1) <> N'\'
  5138.     BEGIN
  5139.         SELECT @destination_folder = @destination_folder + N'\'
  5140.     END
  5141.  
  5142.     -- Check if the destination folder exists 
  5143.     EXEC sp_MSget_file_existence @destination_folder, @directory_exists OUTPUT
  5144.     IF @directory_exists = 0
  5145.     BEGIN
  5146.         RAISERROR(21287, 16, -1)      
  5147.         RETURN (1)
  5148.     END    
  5149.     
  5150.     -- Parse out the last three components in the source folder 
  5151.     -- Note that the source_folder must have a trailing backslash
  5152.     SELECT @bslashindex = 1
  5153.     SELECT @bslashindex2 = 1
  5154.     SELECT @bslashcounter = 0
  5155.     WHILE (@bslashindex <> 0)
  5156.     BEGIN
  5157.         SELECT @bslashindex = CHARINDEX(N'\', @source_folder, @bslashindex + 1)
  5158.         SELECT @bslashcounter = @bslashcounter + 1
  5159.         IF @bslashcounter > 4
  5160.         BEGIN
  5161.             SELECT @bslashindex2 = CHARINDEX(N'\', @source_folder, @bslashindex2 + 1)
  5162.         END    
  5163.     END  
  5164.  
  5165.     SELECT @bslashindex = CHARINDEX(N'\', @source_folder, @bslashindex2 + 1)
  5166.     SELECT @ftporuncdir = SUBSTRING(@source_folder, @bslashindex2 + 1, @bslashindex - @bslashindex2 - 1)
  5167.     SELECT @bslashindex2 = @bslashindex
  5168.  
  5169.     SELECT @bslashindex = CHARINDEX(N'\', @source_folder, @bslashindex2 + 1)
  5170.     SELECT @pubdir = SUBSTRING(@source_folder, @bslashindex2 + 1, @bslashindex - @bslashindex2 - 1) 
  5171.     SELECT @bslashindex2 = @bslashindex
  5172.  
  5173.     SELECT @bslashindex = CHARINDEX(N'\', @source_folder, @bslashindex2 + 1)
  5174.     SELECT @timestampdir = SUBSTRING(@source_folder, @bslashindex2 + 1, @bslashindex - @bslashindex2 - 1) 
  5175.     SELECT @bslashindex2 = @bslashindex
  5176.         
  5177.     -- Create the subdirectory structure underneath the specified snapshot
  5178.     -- folder. Ignore errors for now, we will check whether the directory 
  5179.     -- is successfully created later on.
  5180.  
  5181.     -- Don't suppress output from xp_cmdshell so user knows what's going on
  5182.     -- in case something goes wrong 
  5183.     SELECT @destination_folder = @destination_folder + @ftporuncdir + '\'
  5184.     SELECT @command = 'mkdir "' + fn_escapecmdshellsymbolsremovequotes(@destination_folder) collate database_default + '"'
  5185.     IF (@platform_nt = 1)
  5186.         SELECT @command = '" ' + @command + ' "'
  5187.     EXEC master..xp_cmdshell @command
  5188.     
  5189.     SELECT @destination_folder = @destination_folder + @pubdir + '\'
  5190.     SELECT @command = 'mkdir "' + fn_escapecmdshellsymbolsremovequotes(@destination_folder) collate  database_default + '"'
  5191.     IF (@platform_nt = 1)
  5192.         SELECT @command = '" ' + @command + ' "'
  5193.     EXEC master..xp_cmdshell @command
  5194.  
  5195.     SELECT @destination_folder = @destination_folder + @timestampdir + '\'
  5196.     SELECT @command = 'mkdir "' + fn_escapecmdshellsymbolsremovequotes(@destination_folder) collate database_default + '"'
  5197.     IF (@platform_nt = 1)
  5198.         SELECT @command = '" ' + @command + ' "'
  5199.     EXEC master..xp_cmdshell @command
  5200.  
  5201.     -- Check if the real destination folder exists
  5202.     EXEC sp_MSget_file_existence @destination_folder, @directory_exists OUTPUT
  5203.     IF @directory_exists = 0
  5204.     BEGIN
  5205.         RAISERROR(21288, 16, -1)
  5206.         RETURN (1)
  5207.     END
  5208.  
  5209.     -- Do the actual copying
  5210.     SELECT @command = 'copy "' + fn_escapecmdshellsymbolsremovequotes(@source_folder) collate database_default + '*.*" "' + fn_escapecmdshellsymbolsremovequotes(@destination_folder) collate database_default + '"'    
  5211.     IF (@platform_nt = 1)
  5212.         SELECT @command = '" ' + @command + ' "'
  5213.     
  5214.     EXEC @retcode = master..xp_cmdshell @command
  5215.     
  5216.     IF @retcode <> 0
  5217.         RETURN (1)
  5218.     ELSE
  5219.         RETURN (0)
  5220. END
  5221. go
  5222. EXEC dbo.sp_MS_marksystemobject sp_MScopysnapshot
  5223. go
  5224.  
  5225. --------------------------------------------------------------------------------
  5226. --. sp_copymergesnapshot
  5227. --------------------------------------------------------------------------------
  5228. if exists (select * from sysobjects
  5229.     where type = 'P' and name = 'sp_copymergesnapshot')
  5230. drop procedure sp_copymergesnapshot
  5231. go
  5232. raiserror('Creating procedure sp_copymergesnapshot', 0,1)
  5233. go
  5234. CREATE PROCEDURE sp_copymergesnapshot (
  5235.     @publication          sysname,
  5236.     @destination_folder   nvarchar(255)
  5237.     )
  5238. AS
  5239. BEGIN
  5240.     SET NOCOUNT ON
  5241.     DECLARE @retcode       int
  5242.     DECLARE @source_folder nvarchar(255)
  5243.     SELECT @retcode = 0
  5244.     
  5245.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  5246.     IF @@ERROR <> 0 OR @retcode <> 0
  5247.         RETURN (1)
  5248.  
  5249.     CREATE TABLE #snapshot_folders
  5250.     (
  5251.         id              int identity, 
  5252.         snapshot_folder nvarchar(255) collate database_default
  5253.     )
  5254.     IF @@ERROR <> 0
  5255.     BEGIN
  5256.         RETURN 1
  5257.     END
  5258.  
  5259.     INSERT INTO #snapshot_folders
  5260.     EXEC @retcode = sp_browsemergesnapshotfolder @publication = @publication
  5261.     IF @retcode <> 0 OR @@ERROR <> 0
  5262.     BEGIN
  5263.         GOTO Failure
  5264.     END
  5265.     
  5266.     SELECT @source_folder = (select top 1 snapshot_folder FROM #snapshot_folders ORDER BY id ASC)
  5267.     IF @@ERROR <> 0
  5268.     BEGIN
  5269.         GOTO Failure
  5270.     END        
  5271.     SET ROWCOUNT 0    
  5272.  
  5273.     EXEC @retcode = sp_MScopysnapshot @source_folder,
  5274.                                       @destination_folder
  5275.     IF @retcode <> 0 OR @@ERROR <> 0 
  5276.     BEGIN
  5277.         GOTO Failure
  5278.     END
  5279.  
  5280.     DROP TABLE #snapshot_folders
  5281.     RETURN 0
  5282. Failure:
  5283.     SET ROWCOUNT 0    
  5284.     DROP TABLE #snapshot_folders        
  5285.     RETURN 1
  5286. END
  5287. GO
  5288. EXEC dbo.sp_MS_marksystemobject sp_copymergesnapshot
  5289. go
  5290. grant execute on dbo.sp_copymergesnapshot to public
  5291. go
  5292.  
  5293. --------------------------------------------------------------------------------
  5294. --. sp_copysubscription
  5295. --------------------------------------------------------------------------------
  5296. if exists (select * from sysobjects
  5297.     where type = 'P' and name = 'sp_copysubscription')
  5298. drop procedure sp_copysubscription
  5299. go
  5300. print ''
  5301. print 'Creating procedure sp_copysubscription'
  5302. go
  5303. CREATE PROCEDURE sp_copysubscription (
  5304. @filename nvarchar(260),
  5305. @temp_dir nvarchar(260) = NULL,
  5306. -- Directory contains temp files. If not specified, SQL
  5307. -- server default data directory will be used.
  5308. @overwrite_existing_file bit = 0
  5309. )
  5310. AS
  5311.  
  5312.     SET NOCOUNT ON
  5313.  
  5314.     /*
  5315.     ** Declarations.
  5316.     */
  5317.     declare @cmd nvarchar(4000)
  5318.     declare @retcode int
  5319.     declare @data_path nvarchar(260)
  5320.     declare @subscriber_srvid     int
  5321.     declare @subscriber_db        sysname
  5322.     declare @backup_path nvarchar(260)
  5323.     declare @temp_data_path nvarchar(260)
  5324.     declare @temp_log_path nvarchar(260)
  5325.     declare @retention            int
  5326.     declare @retention_date       datetime
  5327.     declare @pubid                 uniqueidentifier
  5328.  
  5329.  
  5330.     /*
  5331.     * Initializations
  5332.     */
  5333.     select @retcode = 0
  5334.     select @subscriber_srvid = 0
  5335.     select @subscriber_db = db_name()
  5336.  
  5337.     -- We only support single file attach. Check to make sure
  5338.     -- there are only 2 files, one data file and one log file
  5339.     if (select count(*) from sysfiles) > 2
  5340.     begin
  5341.         raiserror(21212,16, -1)
  5342.         return 1
  5343.     end
  5344.  
  5345.     /* Make sure all tran sub allows attach */
  5346.     declare @publication                 sysname
  5347.     declare @publisher                    sysname
  5348.     declare @tran_found                    bit
  5349.     declare @merge_found                bit
  5350.     select @tran_found = 0
  5351.     select @merge_found = 0
  5352.  
  5353.     /* 
  5354.     ** Make sure all merge subscriptions in the current database 
  5355.     ** have allow_subscription_copy set to TRUE
  5356.     ** and there are no push subscriptions. 
  5357.     */
  5358.     if exists (select * from sysobjects where name = 'MSsubscription_agents')
  5359.     begin
  5360.         set @publisher = NULL
  5361.         -- Not using @publication because share agent case.
  5362.         select top 1 @publisher = publisher from MSsubscription_agents where
  5363.             allow_subscription_copy = 0
  5364.         IF @publisher is not null
  5365.         BEGIN
  5366.             RAISERROR(21236, 16, -1, @publisher)
  5367.             RETURN (1)
  5368.         END
  5369.  
  5370.         set @publisher = null
  5371.         select top 1 @publisher = publisher from MSreplication_subscriptions where
  5372.             subscription_type = 0
  5373.         IF @publisher is not null
  5374.         BEGIN
  5375.             RAISERROR(21237, 16, -1, @publisher)            
  5376.             RETURN (1)
  5377.         END
  5378.         if exists (select * from MSsubscription_agents)
  5379.             select @tran_found = 1
  5380.     end            
  5381.  
  5382.     /* 
  5383.     ** Make sure all merge subscriptions in the current database 
  5384.     ** have allow_subscription_copy set to TRUE
  5385.     ** and there are no push subscriptions. 
  5386.     */
  5387.     if exists (select * from sysobjects where name = 'sysmergepublications')
  5388.         begin
  5389.             set @publication = NULL
  5390.             select top 1 @publication = name from sysmergepublications where
  5391.                 allow_subscription_copy = 0
  5392.             IF @publication is not null
  5393.                 BEGIN
  5394.                     RAISERROR (21204, 16, -1, @publication)    
  5395.                     RETURN (1)
  5396.                 END
  5397.  
  5398.             set @publication = null
  5399.             select top 1 @publication = p.name from sysmergepublications p, 
  5400.                 sysmergesubscriptions s where
  5401.                 p.pubid = s.pubid and
  5402.                 s.subid <> s.pubid and 
  5403.                 db_name = db_name() collate database_default and 
  5404.                 subscriber_server = convert(nvarchar(4000), SERVERPROPERTY('ServerName')) collate database_default  and
  5405.                 s.subscription_type = 0
  5406.             IF @publication is not null
  5407.             BEGIN
  5408.                 RAISERROR(21238, 16, -1, @publication)            
  5409.                 RETURN (1)
  5410.             END
  5411.  
  5412.             -- Does db contains subscriptions?
  5413.             if exists (select * from sysmergesubscriptions where subid <> pubid and 
  5414.                 db_name = db_name() collate database_default and 
  5415.                 subscriber_server = convert(nvarchar(4000), SERVERPROPERTY('ServerName')) collate database_default)
  5416.                 select @merge_found = 1
  5417.  
  5418.             /* Retention check : Make sure that the subscription copy is not too old */
  5419.             declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT p.name, p.pubid, p.retention from sysmergepublications p, sysmergesubscriptions s 
  5420.                 where s.subid=p.pubid and s.pubid=p.pubid for read only
  5421.             open PC
  5422.             fetch PC into @publication, @pubid, @retention 
  5423.             
  5424.             WHILE (@@fetch_status <> -1)
  5425.                 BEGIN
  5426.                     /* Compute the retention period cutoff dates per publication */
  5427.                     select @retention_date = dateadd(day, -@retention, getdate())
  5428.                        if @retention is not NULL and @retention > 0
  5429.                     begin
  5430.                         if not exists (select coldate from sysmergearticles , MSmerge_genhistory 
  5431.                                             where    nickname = art_nick 
  5432.                                                     and coldate > @retention_date 
  5433.                                                     and sysmergearticles.pubid = @pubid)
  5434.                             begin
  5435.                                 RAISERROR (21306, 16, -1, @publication)
  5436.                                 return (1)
  5437.                             end                                
  5438.                     end
  5439.                     fetch PC into @publication, @pubid, @retention
  5440.                 END
  5441.  
  5442.         end            
  5443.  
  5444.     if @tran_found = 0 and @merge_found = 0
  5445.     begin
  5446.         raiserror(21239, 16 , -1)
  5447.         return (1)
  5448.     end
  5449.     
  5450.     -- Security check
  5451.     -- Only DBO or sysadmin can do this
  5452.     -- The user also must have create db permissions.
  5453.     exec @retcode = dbo.sp_MSreplcheck_subscribe
  5454.     IF @retcode <> 0 or @@error <> 0
  5455.         return 1
  5456.  
  5457.     if @overwrite_existing_file is null
  5458.         set @overwrite_existing_file = 0
  5459.  
  5460.     -- Check to see if the file already exists
  5461.     declare @exists bit
  5462.  
  5463.     if @overwrite_existing_file = 0
  5464.     begin
  5465.         exec @retcode = dbo.sp_MSget_file_existence @filename, @exists output
  5466.         if @@error <> 0 or @retcode <> 0
  5467.             return 1
  5468.         if @exists <> 0 
  5469.         begin
  5470.             raiserror(21214, 16, -1, @filename)
  5471.             return 1
  5472.         end
  5473.     end
  5474.  
  5475.     -- Check to see if have write permissions to the file location.
  5476.     -- Try create the file
  5477.     -- Echo text can be anything.
  5478.     select @cmd = 'echo Subscription copy failed. > "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + '"'
  5479.     exec @retcode = master.dbo.xp_cmdshell @cmd, NO_OUTPUT
  5480.     if @@error <> 0 or @retcode <> 0
  5481.     begin
  5482.         raiserror(21247, 16, -1, @filename)
  5483.         select @retcode = 1
  5484.         goto Cleanup
  5485.     end    
  5486.     -- File should be created.
  5487.     exec @retcode = dbo.sp_MSget_file_existence @filename, @exists output
  5488.     if @@error <> 0 or @retcode <> 0
  5489.     begin
  5490.         select @retcode = 1
  5491.         goto Cleanup
  5492.     end
  5493.     if @exists = 0
  5494.     begin
  5495.         raiserror(21247,16, -1, @filename)
  5496.         select @retcode = 1
  5497.         goto Cleanup
  5498.     end
  5499.  
  5500.     /*
  5501.     ** Get the MSSQL DATA path. Note that users can have a SQLDataRoot directory different from SQLPath
  5502.     */
  5503.     if @temp_dir is null
  5504.     begin
  5505.         exec @retcode = master.dbo.sp_MSget_setup_paths
  5506.             @data_path = @temp_dir output
  5507.         IF @retcode <> 0 or @@error <> 0
  5508.             return 1
  5509.         select @temp_dir = @temp_dir + '\DATA\'
  5510.     end
  5511.     else
  5512.     begin
  5513.         -- Check to make sure working dir is valid.
  5514.         exec @retcode = dbo.sp_MSget_file_existence @temp_dir, @exists output
  5515.         if @@error <> 0 or @retcode <> 0
  5516.         begin
  5517.             select @retcode = 1
  5518.             goto Cleanup
  5519.         end
  5520.         if @exists = 0
  5521.         begin
  5522.             raiserror (21037, 16, -1, @temp_dir)        
  5523.             select @retcode = 1
  5524.             goto Cleanup
  5525.         end
  5526.         if substring(@temp_dir, len(@temp_dir), 1) <> '\'
  5527.             select @temp_dir = @temp_dir + '\'
  5528.     end
  5529.  
  5530.     -- Get temp db name
  5531.     -- Use a guid to avoid name colision.
  5532.     declare @dbname sysname
  5533.     select @dbname = db_name()
  5534.     declare @temp_db_name sysname
  5535.     declare @guid_name nvarchar(36)
  5536.     select @guid_name =  convert (nvarchar(36), newid())
  5537.  
  5538.     select @temp_db_name = 'repl_sub_restore_' + @guid_name
  5539.  
  5540.     select @backup_path = @temp_dir + @temp_db_name + '.bak'
  5541.  
  5542.     -- Create table used to signal attach or restored process to do different things
  5543.     if not exists (select * from sysobjects where name = 'MSreplication_restore_stage')
  5544.     begin 
  5545.         CREATE TABLE dbo.MSreplication_restore_stage
  5546.         (
  5547.         stage_id int -- not used for now
  5548.         )
  5549.         IF @@ERROR <> 0
  5550.             return 1
  5551.     end
  5552.     
  5553.     -- First backup the database to the file given
  5554.     -- Overwrite the existing file with INIT option.
  5555.     BACKUP DATABASE @dbname TO DISK = @backup_path WITH INIT
  5556.     if @@error<> 0
  5557.     begin
  5558.         select @retcode = 1
  5559.         goto Cleanup
  5560.     end
  5561.  
  5562.  
  5563.     -- Restore it to a temporary working database
  5564.     -- Get phy data and log file name for the temp db
  5565.     select @temp_data_path = @temp_dir + @temp_db_name + '.mdf'
  5566.     select @temp_log_path = @temp_dir + @temp_db_name + '.ldf'
  5567.  
  5568.     -- Get the command
  5569.     select @cmd = 'restore database ' + quotename(@temp_db_name) + ' from disk = ' 
  5570.         + quotename(@backup_path,'''') + ' with replace, move '
  5571.  
  5572.     -- Get the logical file name for data file.
  5573.     select @cmd = @cmd + quotename(rtrim(name),'''') from sysfiles where
  5574.         (status & 0x40) = 0
  5575.  
  5576.     -- Use passed in filename as phy data file name for the temp db
  5577.  
  5578.     -- Use the passed in file as phy data file for the temp db
  5579.     select @cmd = @cmd + ' to ' + quotename(@temp_data_path,'''') + ', move '
  5580.  
  5581.     -- Get the logical file name for the log file
  5582.     select @cmd = @cmd + quotename(rtrim(name),'''') from sysfiles where
  5583.         (status & 0x40) <> 0
  5584.  
  5585.     -- Use the passed in file as phy file for the temp db
  5586.     select @cmd = @cmd + ' to ' + quotename(@temp_log_path,'''') + ' '
  5587.     exec (@cmd)
  5588.     if @@error<> 0
  5589.     begin
  5590.         select @retcode = 1
  5591.         goto Cleanup
  5592.     end
  5593.  
  5594.     -- Once we successfully restored, we delete to back up file to save disk space.
  5595.     if @backup_path is not null
  5596.     begin
  5597.         select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@backup_path) collate database_default + '"' 
  5598.         EXEC master..xp_cmdshell @cmd, NO_OUTPUT
  5599.         set @backup_path = null
  5600.     end
  5601.  
  5602.     -- Prepare the database for detach. 2 things will be done
  5603.     -- 1. Set a flag to indicate that this is a prepare sub db for detach
  5604.     -- 2. For merge, create table to store sysservers info for later fixing up after attach
  5605.     select @cmd = quotename(@temp_db_name) + '.dbo.sp_MSprepare_sub_for_detach'
  5606.     
  5607.     exec @retcode = @cmd @subscriber_srvid = @subscriber_srvid, @subscriber_db = @subscriber_db
  5608.     if @retcode<>0 or @@error<>0
  5609.     begin
  5610.         select @retcode = 1
  5611.         goto Cleanup
  5612.     end
  5613.  
  5614.     -- Shink the size of the temp db before detach
  5615.     DBCC SHRINKDATABASE (@temp_db_name, 10)
  5616.     if @@error <> 0
  5617.         goto Cleanup
  5618.  
  5619.     -- detach the database
  5620.     -- Wait for the db to be closed
  5621.     WAITFOR DELAY '00:00:00.500'
  5622.     exec @retcode = sp_detach_db @temp_db_name
  5623.     if @retcode<>0 or @@error<>0
  5624.     begin
  5625.         select @retcode = 1
  5626.         goto Cleanup
  5627.     end
  5628.  
  5629.     -- Delete the log file to save disk space
  5630.     if @temp_log_path is not null
  5631.     begin
  5632.         select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@temp_log_path) collate database_default + '"' 
  5633.         EXEC master..xp_cmdshell @cmd, NO_OUTPUT
  5634.         set @temp_log_path = null
  5635.     end
  5636.  
  5637.     -- Compress the file
  5638.     exec @retcode = master..xp_makecab
  5639.         @cabfilename = @filename,
  5640.         @compression_mode ='mszip',
  5641.         @verbose_level = 0,
  5642.         @filename1 = @temp_data_path
  5643.     if @retcode<>0 or @@error<>0
  5644.     begin
  5645.         select @retcode = 1
  5646.         goto Cleanup
  5647.     end
  5648.  
  5649.  
  5650. Cleanup:
  5651.     if exists (select * from sysobjects where name = 'MSreplication_restore_stage')
  5652.         drop table dbo.MSreplication_restore_stage
  5653.  
  5654.  
  5655.     if exists (select * from master..sysdatabases where name = @temp_db_name collate database_default)
  5656.     begin
  5657.         select @cmd = 'drop database ' + quotename(@temp_db_name)
  5658.         exec (@cmd)
  5659.     end
  5660.  
  5661.     if @backup_path is not null
  5662.     begin
  5663.         select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@backup_path) collate database_default + '"' 
  5664.         EXEC master..xp_cmdshell @cmd, NO_OUTPUT
  5665.     end
  5666.  
  5667.     if @temp_data_path is not null
  5668.     begin
  5669.         select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@temp_data_path) collate database_default + '"' 
  5670.         EXEC master..xp_cmdshell @cmd, NO_OUTPUT
  5671.     end
  5672.  
  5673.     if @temp_log_path is not null
  5674.     begin
  5675.         select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@temp_log_path) collate database_default + '"' 
  5676.         EXEC master..xp_cmdshell @cmd, NO_OUTPUT
  5677.     end
  5678.  
  5679.     if @retcode <> 0
  5680.     begin
  5681.         select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + '"' 
  5682.         EXEC master..xp_cmdshell @cmd, NO_OUTPUT
  5683.     end
  5684.  
  5685.     return @retcode
  5686. go
  5687. EXEC dbo.sp_MS_marksystemobject sp_copysubscription
  5688. GO
  5689. grant execute on dbo.sp_copysubscription to public
  5690. go
  5691.  
  5692. --------------------------------------------------------------------------------
  5693. --. sp_attachsubscription
  5694. --------------------------------------------------------------------------------
  5695. if exists (select * from sysobjects
  5696.     where type = 'P' and name = 'sp_attachsubscription')
  5697. drop procedure sp_attachsubscription
  5698. go
  5699. print ''
  5700. print 'Creating procedure sp_attachsubscription'
  5701. go
  5702. CREATE PROCEDURE sp_attachsubscription (
  5703. @dbname    sysname,
  5704. @filename nvarchar(260),
  5705. @subscriber_security_mode        int = NULL,                        /* 0 standard; 1 integrated */
  5706. @subscriber_login                sysname = NULL,
  5707. @subscriber_password            sysname = NULL
  5708. )
  5709. AS
  5710.  
  5711.     SET NOCOUNT ON
  5712.  
  5713.     /*
  5714.     ** Declarations.
  5715.     */
  5716.     declare @cmd nvarchar(4000)
  5717.     declare @retcode int
  5718.     DECLARE @platform_nt binary
  5719.     declare @copy_created bit
  5720.     declare @exists bit
  5721.  
  5722.     select @platform_nt = 0x1    
  5723.     select @retcode = 0
  5724.     select @copy_created = 0
  5725.     select @exists = 0
  5726.  
  5727.     -- Parameter check: @subscriber_security_mode
  5728.     if @subscriber_security_mode is null
  5729.     begin
  5730.         if ( platform() & @platform_nt ) = @platform_nt
  5731.             select @subscriber_security_mode = 1
  5732.         else
  5733.             select @subscriber_security_mode = 0
  5734.     end    
  5735.  
  5736.     if ( ( platform() & @platform_nt ) <> @platform_nt and @subscriber_security_mode = 1 )
  5737.     begin
  5738.         RAISERROR(21038, 16, -1)
  5739.         RETURN (1)
  5740.     end
  5741.  
  5742.     if (@subscriber_security_mode = 0) and (@subscriber_login IS NULL or rtrim(@subscriber_login) = '')
  5743.         set @subscriber_login = 'sa'
  5744.  
  5745.     -- Check to make sure the database does not exists.
  5746.     if exists (select * from master..sysdatabases where name = @dbname collate database_default)
  5747.     begin
  5748.         raiserror(20621, 16, -1, @dbname)
  5749.         return (1)
  5750.     end
  5751.  
  5752.     -- Check to see if users has permissions to create database
  5753.     -- permissions() have to be run in master to return create db permission.
  5754.     declare @pm int
  5755.     exec @retcode = master.dbo.sp_executesql N'select @pm = permissions()', N'@pm int output', @pm output
  5756.     if @@error <> 0 or @retcode <> 0
  5757.         return 1
  5758.     if @pm & 1 = 0
  5759.     begin
  5760.         raiserror(20618, 16, -1)
  5761.         return 1
  5762.     end
  5763.  
  5764.     -- Decompress the file
  5765.     -- We have to copy the file to another location first. 
  5766.     -- (cannot use source as destination')
  5767.     declare @temp_copy nvarchar(260)
  5768.     declare @file_dir nvarchar(260)
  5769.     declare @file_name nvarchar(260)
  5770.     declare @dir_cmd nvarchar(260)
  5771.     -- Set @drive_cmd if needed 
  5772.     -- Set temp copy to be the file directory first
  5773.     -- Note @file_dir include '\'
  5774.     if (charindex('\', @filename, 1) = 0)
  5775.     begin
  5776.         select @file_dir = ''
  5777.         select @file_name = @filename
  5778.     end
  5779.     else
  5780.     begin
  5781.         select @file_dir = left(@filename,len(@filename) + 1 - 
  5782.             charindex('\', reverse(@filename), 1))
  5783.         select @file_name = right(@filename, len(@filename) - len(@file_dir))
  5784.     end
  5785.     -- Get guid name
  5786.     declare @guid_name nvarchar(36)
  5787.     select @guid_name =  convert (nvarchar(36), newid())
  5788.     select @temp_copy = @file_dir + @guid_name + '.tmp'
  5789.  
  5790.  
  5791.     -- copy file
  5792.     select @cmd = 'copy "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + '" "' + fn_escapecmdshellsymbolsremovequotes(@temp_copy) collate database_default + '"'
  5793.     exec @retcode = master.dbo.xp_cmdshell @cmd, NO_OUTPUT
  5794.     if @@error <> 0 or @retcode <> 0
  5795.     begin
  5796.         raiserror(21248, 16, -1, @filename)
  5797.         select @retcode = 1
  5798.         goto Cleanup
  5799.     end    
  5800.  
  5801.     exec @retcode = dbo.sp_MSget_file_existence @temp_copy, @exists output
  5802.     if @@error <> 0 or @retcode <> 0
  5803.     begin
  5804.         select @retcode = 1
  5805.         goto Cleanup
  5806.     end
  5807.     if @exists = 0
  5808.     begin
  5809.         raiserror(21247, 16, -1, @temp_copy)        
  5810.         select @retcode = 1
  5811.         goto Cleanup
  5812.     end
  5813.  
  5814.     select @copy_created = 1
  5815.  
  5816.     -- decompress
  5817.     exec @retcode = master.dbo.xp_unpackcab 
  5818.         @cabfilename = @temp_copy,
  5819.         @destination_folder = @file_dir,
  5820.         @verbose_level = 0,
  5821.         @destination_file = @file_name,
  5822.         @suppress_messages = 1
  5823.         
  5824.     if @@error <> 0 
  5825.     begin
  5826.         select @retcode = 1
  5827.         goto Cleanup
  5828.     end
  5829.  
  5830.     if @retcode in (1030,1029,2005)
  5831.     begin
  5832.         raiserror(20609, 16, -1, @filename)
  5833.         select @retcode = 1
  5834.         goto Cleanup
  5835.     end    
  5836.     else if @retcode <> 0
  5837.     -- re-issue the command to get errors
  5838.     begin
  5839.         exec @retcode = master.dbo.xp_unpackcab 
  5840.             @cabfilename = @temp_copy,
  5841.             @destination_folder = @file_dir,
  5842.             @verbose_level = 0,
  5843.             @destination_file = @file_name,
  5844.             @suppress_messages = 0
  5845.         select @retcode = 1
  5846.         goto Cleanup
  5847.     end
  5848.  
  5849.     -- Attach
  5850.     exec @retcode = dbo.sp_attach_single_file_db
  5851.         @dbname = @dbname,
  5852.         @physname = @filename
  5853.     if @retcode<>0 or @@error<>0
  5854.     begin
  5855.         raiserror(21248, 16, -1, @filename)
  5856.         select @retcode = 1
  5857.         goto Cleanup
  5858.     end
  5859.  
  5860.  
  5861.     -- Prepare the database for detach. 2 things will be done
  5862.     -- 1. Set a flag to indicate that this is a prepare sub db for detach
  5863.     -- 2. For merge, create table to store sysservers info for later fixing up after attach
  5864.     select @cmd = quotename(@dbname) + '.dbo.sp_MSrestore_sub'
  5865.     exec @retcode = @cmd
  5866.         @subscriber_security_mode = @subscriber_security_mode,    
  5867.         @subscriber_login = @subscriber_login,
  5868.         @subscriber_password = @subscriber_password
  5869.     if @retcode<>0 or @@error<>0
  5870.     begin
  5871.         select @retcode = 1
  5872.         goto Cleanup
  5873.     end
  5874.  
  5875. Cleanup:
  5876.     if @retcode <> 0
  5877.     begin
  5878.         -- The files will be deleted if some thing failed. 
  5879.         if exists (select * from master..sysdatabases where name = @dbname collate database_default)
  5880.             begin
  5881.                 select @cmd = 'drop database ' + quotename(@dbname)
  5882.                 exec (@cmd)
  5883.             end                
  5884.     end
  5885.  
  5886.     if @temp_copy is not null
  5887.     begin
  5888.         -- Restore the original file, ignore errors
  5889.         if @retcode <> 0 and @copy_created = 1
  5890.         begin
  5891.             select @cmd = 'copy "' + fn_escapecmdshellsymbolsremovequotes(@temp_copy) collate database_default + '" "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + '"'
  5892.             exec master.dbo.xp_cmdshell @cmd, NO_OUTPUT
  5893.         end
  5894.  
  5895.         -- Delete the temp file.
  5896.         select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@temp_copy) collate database_default+ '"' 
  5897.         EXEC master..xp_cmdshell @cmd, NO_OUTPUT
  5898.     end
  5899.  
  5900.     return @retcode
  5901. go
  5902. EXEC dbo.sp_MS_marksystemobject sp_attachsubscription
  5903. GO
  5904. grant execute on dbo.sp_attachsubscription to public
  5905. go
  5906. --------------------------------------------------------------------------------
  5907. --. sp_browsesnapshotfolder
  5908. --------------------------------------------------------------------------------
  5909. if exists (select * from sysobjects
  5910.     where type = 'P' and name = 'sp_browsesnapshotfolder')
  5911. drop procedure sp_browsesnapshotfolder
  5912. go
  5913. raiserror('Creating procedure sp_browsesnapshotfolder', 0,1)
  5914. go
  5915. CREATE PROCEDURE sp_browsesnapshotfolder (
  5916.     @publication    sysname,
  5917.     @subscriber     sysname = NULL,
  5918.     @subscriber_db  sysname = NULL
  5919.     )
  5920. AS
  5921. BEGIN
  5922.     SET NOCOUNT ON
  5923.     DECLARE @retcode        INT
  5924.     DECLARE @publisher      sysname
  5925.     DECLARE @publisher_db   sysname
  5926.     DECLARE @distributor    sysname
  5927.     DECLARE @distributiondb sysname
  5928.     DECLARE @distproc       nvarchar(300)
  5929.     DECLARE @article_id     INT
  5930.     
  5931.     SELECT @retcode = 0
  5932.     SELECT @publisher = NULL
  5933.     SELECT @publisher_db = DB_NAME()
  5934.     SELECT @distributor = NULL
  5935.     SELECT @distributiondb = NULL
  5936.     SELECT @article_id = NULL
  5937.     
  5938.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  5939.     IF @@ERROR <> 0 or @retcode <> 0
  5940.         return (1)
  5941.  
  5942.     -- Either both of @subscriber and @subscriber_db are NULL or
  5943.     -- both of them have to be non-null
  5944.     IF ((@subscriber IS NULL OR @subscriber = N'') 
  5945.         AND @subscriber_db IS NOT NULL AND @subscriber_db <> N'') OR
  5946.        ((@subscriber_db IS NULL OR @subscriber_db = N'') 
  5947.         AND @subscriber IS NOT NULL AND @subscriber <> N'')
  5948.     BEGIN
  5949.         RAISERROR(21148, 16, -1)
  5950.     END
  5951.     
  5952.     IF EXISTS (SELECT * FROM sysobjects WHERE name = N'syspublications') AND
  5953.        EXISTS (SELECT * FROM sysobjects WHERE name = N'sysextendedarticlesview')
  5954.     BEGIN    
  5955.         SELECT @publisher = @@SERVERNAME
  5956.     
  5957.         -- Get the smallest article id for the publication since 
  5958.         -- method for identifying a publication is not readily available 
  5959.         -- on the distributor
  5960.  
  5961.         SELECT @article_id = MIN(artid) 
  5962.           FROM sysextendedarticlesview sa
  5963.     INNER JOIN syspublications sp
  5964.             ON sa.pubid = sp.pubid
  5965.          WHERE sp.name = @publication
  5966.  
  5967.         IF @article_id IS NULL
  5968.         BEGIN
  5969.             RAISERROR(20026, 16, -1, @publication)
  5970.         END         
  5971.  
  5972.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  5973.                                                @distribdb = @distributiondb OUTPUT
  5974.         IF @retcode <> 0
  5975.             RETURN @retcode
  5976.     
  5977.         SELECT @distributor = RTRIM(@distributor)
  5978.     
  5979.         IF LOWER(@@SERVERNAME) <> LOWER(@distributor)
  5980.         BEGIN
  5981.             SELECT @distproc = @distributor + '.' + @distributiondb + 
  5982.                                '.dbo.sp_MSbrowsesnapshotfolder'
  5983.         END
  5984.         ELSE
  5985.         BEGIN
  5986.             SELECT @distproc = @distributiondb + '.dbo.sp_MSbrowsesnapshotfolder'
  5987.         END
  5988.         EXECUTE @retcode = @distproc
  5989.                     @publisher = @publisher, 
  5990.                     @publisher_db = @publisher_db,
  5991.                     @article_id = @article_id,
  5992.                     @subscriber = @subscriber,
  5993.                     @subscriber_db = @subscriber_db
  5994.         RETURN @retcode
  5995.     END
  5996.     ELSE
  5997.     BEGIN
  5998.         RAISERROR(21149, 16, -1, @publisher_db)
  5999.         RETURN 1
  6000.     END
  6001. END
  6002. GO
  6003. EXEC dbo.sp_MS_marksystemobject sp_browsesnapshotfolder
  6004. go
  6005. grant execute on dbo.sp_browsesnapshotfolder to public
  6006. go
  6007. --------------------------------------------------------------------------------
  6008. --. sp_copysnapshot
  6009. --------------------------------------------------------------------------------
  6010. if exists (select * from sysobjects
  6011.     where type = 'P' and name = 'sp_copysnapshot')
  6012. drop procedure sp_copysnapshot
  6013. go
  6014.  
  6015. raiserror('Creating procedure sp_copysnapshot', 0,1)
  6016. go
  6017. CREATE PROCEDURE sp_copysnapshot (
  6018.     @publication        sysname,
  6019.     @destination_folder nvarchar(255),
  6020.     @subscriber         sysname = NULL,
  6021.     @subscriber_db      sysname = NULL
  6022.     )
  6023. AS
  6024. BEGIN
  6025.     SET NOCOUNT ON
  6026.     DECLARE @retcode       int
  6027.     DECLARE @source_folder nvarchar(255)
  6028.     SELECT @retcode = 0
  6029.     
  6030.     -- security check, db_owner
  6031.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  6032.     IF @@ERROR <> 0 or @retcode <> 0
  6033.         return (1)
  6034.  
  6035.     CREATE TABLE #snapshot_folders
  6036.     (
  6037.         id              int identity,
  6038.         snapshot_folder nvarchar(255) collate database_default
  6039.     )
  6040.     IF @@ERROR <> 0
  6041.     BEGIN
  6042.         RETURN 1
  6043.     END
  6044.  
  6045.     INSERT INTO #snapshot_folders
  6046.     EXEC @retcode = sp_browsesnapshotfolder @publication = @publication,
  6047.                                             @subscriber = @subscriber,
  6048.                                             @subscriber_db = @subscriber_db
  6049.     IF @retcode <> 0 OR @@ERROR <> 0
  6050.     BEGIN
  6051.         GOTO Failure
  6052.     END
  6053.  
  6054.     SELECT @source_folder = (select top 1 snapshot_folder FROM #snapshot_folders ORDER BY id)
  6055.     IF @@ERROR <> 0
  6056.     BEGIN
  6057.         GOTO Failure
  6058.     END        
  6059.     SET ROWCOUNT 0
  6060.  
  6061.     EXEC @retcode = sp_MScopysnapshot @source_folder,
  6062.                                       @destination_folder
  6063.     IF @retcode <> 0 OR @@ERROR <> 0 
  6064.     BEGIN
  6065.         GOTO Failure
  6066.     END
  6067.  
  6068.     DROP TABLE #snapshot_folders
  6069.     RETURN 0
  6070. Failure:
  6071.     SET ROWCOUNT 0
  6072.     DROP TABLE #snapshot_folders        
  6073.     RETURN 1
  6074. END
  6075. GO
  6076. EXEC dbo.sp_MS_marksystemobject sp_copysnapshot
  6077. go
  6078. grant execute on dbo.sp_copysnapshot to public
  6079. go
  6080.  
  6081. --------------------------------------------------------------------------------
  6082. --. sp_getagentoffloadinfo
  6083. --------------------------------------------------------------------------------
  6084. if exists (select * from sysobjects
  6085.     where type = 'P' and name = 'sp_getagentoffloadinfo')
  6086. drop procedure sp_getagentoffloadinfo
  6087. go
  6088. print ''
  6089. print 'Creating procedure sp_getagentoffloadinfo'
  6090. go
  6091. CREATE PROCEDURE sp_getagentoffloadinfo (
  6092.     @job_id         VARBINARY(16)
  6093. ) AS
  6094.     SET NOCOUNT ON
  6095.     DECLARE @retcode        INT
  6096.     DECLARE @distributor    sysname
  6097.     DECLARE @distributiondb sysname
  6098.     DECLARE @distproc       NVARCHAR(300)
  6099.  
  6100.     SELECT @retcode = 0
  6101.     SELECT @distributor    = NULL
  6102.     SELECT @distributiondb = NULL
  6103.  
  6104.     -- security check, db_owner
  6105.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  6106.     IF @@ERROR <> 0 or @retcode <> 0
  6107.         return (1)
  6108.  
  6109.  
  6110.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  6111.                                            @distribdb = @distributiondb OUTPUT
  6112.  
  6113.     IF @retcode <> 0
  6114.         RETURN @retcode
  6115.  
  6116.     SELECT @distributor = RTRIM(@distributor)
  6117.  
  6118.     SELECT @distproc = @distributor + '.' + @distributiondb + 
  6119.                            '.dbo.sp_MSgetagentoffloadinfo'
  6120.  
  6121.     EXECUTE @retcode = @distproc 
  6122.                 @job_id = @job_id
  6123.  
  6124.     RETURN @retcode
  6125. GO
  6126. EXEC dbo.sp_MS_marksystemobject sp_getagentoffloadinfo
  6127. GO
  6128. grant execute on sp_getagentoffloadinfo to public
  6129. go
  6130.  
  6131. --------------------------------------------------------------------------------
  6132. --.    System objects (replcom.sql)
  6133. --------------------------------------------------------------------------------
  6134.  
  6135. --------------------------------------------------------------------------------
  6136. --. sp_adddistributiondb
  6137. --------------------------------------------------------------------------------
  6138. if exists (select * from sysobjects
  6139.     where type = 'P' and name = 'sp_adddistributiondb')
  6140. drop procedure sp_adddistributiondb
  6141. go
  6142. raiserror('Creating procedure sp_adddistributiondb', 0,1)
  6143. go
  6144.  
  6145. CREATE PROCEDURE sp_adddistributiondb (
  6146.     @database sysname,
  6147.     @data_folder nvarchar(255) = NULL,
  6148.     @data_file nvarchar(255) = NULL,            /* physical file name */
  6149.     @data_file_size int = 2,                    /* Default: 2MB */            
  6150.     @log_folder nvarchar(255) = NULL,
  6151.     @log_file nvarchar(255) = NULL,             /* physical file name */
  6152.     @log_file_size int = 0,
  6153.     @min_distretention int = 0,                 /* min distribution retention period in hours */
  6154.     @max_distretention int = 72,                /* max distribution retention period in hours */
  6155.     @history_retention int = 48,                /* history retention period in hours */
  6156.     @security_mode int = 0,                     /* distributor login security 0 standard 1 integrated */
  6157.     @login sysname = 'sa',                      /* standard login name */
  6158.     @password sysname = NULL,                   /* standard login password */
  6159.     @createmode int = 0,  /* 0: use create db for attach (recommended), 
  6160.                             1: create db or use existing but no attach (this is the old way), 
  6161.                             2: create for instdist and detach only */
  6162.     @from_scripting bit = 0
  6163.     ) AS
  6164.  
  6165.     SET NOCOUNT ON
  6166.  
  6167.     /*
  6168.     ** Declarations.
  6169.     */
  6170.     DECLARE @data_path nvarchar(512)
  6171.     DECLARE @log_path nvarchar(512)
  6172.     
  6173.     DECLARE @data_path_quoted_for_copy nvarchar(512)
  6174.     DECLARE @log_path_quoted_for_copy nvarchar(512)
  6175.  
  6176.     DECLARE @logical_data_file nvarchar(255)
  6177.     DECLARE @logical_log_file nvarchar(255)
  6178.     DECLARE @canneddbdata_file nvarchar(255)
  6179.     DECLARE @canneddblog_file nvarchar(255)
  6180.     DECLARE @filecopy_cmd nvarchar(255)
  6181.     DECLARE @file_exists bit
  6182.     DECLARE @data_file_preexists int
  6183.     DECLARE @log_file_preexists int
  6184.     DECLARE @osql_path nvarchar(260)
  6185.     DECLARE @osql_cmd nvarchar(1000)
  6186.     DECLARE @osql_for_nt int
  6187.     DECLARE @devnum int
  6188.     --DECLARE @num_pages int
  6189.     DECLARE @retcode int
  6190.     DECLARE @reg_key nvarchar(255)
  6191.     DECLARE @agentname nvarchar(100)
  6192.     DECLARE @command nvarchar (2048)
  6193.     DECLARE @distbit int
  6194.     DECLARE @install_path nvarchar(255)
  6195.     DECLARE @mssql_data_path nvarchar(255)
  6196.     DECLARE @on_clause nvarchar(512)
  6197.     DECLARE @logon_clause nvarchar(512)
  6198.     DECLARE @distproc nvarchar(255)
  6199.     DECLARE @major_version int
  6200.     DECLARE @db_exists bit
  6201.     DECLARE @trunc_log_bit int
  6202.     DECLARE @description nvarchar(100)
  6203.     DECLARE @category_name sysname
  6204.     DECLARE @createmode_attach int
  6205.     DECLARE @createmode_noattach int
  6206.     DECLARE @createmode_fordetach int
  6207.  
  6208.     --DECLARE @filegrowth nvarchar(10)
  6209.     DECLARE @data_file_size_str nvarchar(10)
  6210.     DECLARE @log_file_size_str nvarchar(10)
  6211.     DECLARE @platform_nt binary
  6212.  
  6213.     --DECLARE @max_datafile_size int
  6214.     --DECLARE @max_logfile_size int
  6215.     
  6216.     IF @password = N''
  6217.         select @password = NULL
  6218.  
  6219.     select @platform_nt = 0x1
  6220.     --select @filegrowth = N'512KB'
  6221.  
  6222.     -- on error, delete the data and log files only if they didn't pre-exist.
  6223.     -- by default, assume they pre-exist.
  6224.     select @data_file_preexists = 1
  6225.     select @log_file_preexists = 1
  6226.     select @file_exists = 0
  6227.  
  6228.     if (@data_file_size IS NULL) or (@data_file_size = 0)
  6229.         select @data_file_size_str = N'512KB'
  6230.     else
  6231.         select @data_file_size_str = convert(nvarchar(10), @data_file_size)
  6232.  
  6233.     if (@log_file_size IS NULL) or (@log_file_size = 0)
  6234.         select @log_file_size_str = N'512KB'
  6235.     else
  6236.         select @log_file_size_str = convert(nvarchar(10), @log_file_size)
  6237.     
  6238.     --if (@data_file_size > 16)
  6239.     --  select @max_datafile_size = @data_file_size
  6240.     --else
  6241.     --  select @max_datafile_size = 16
  6242.     
  6243.     --if (@log_file_size > 16)
  6244.     --  select @max_logfile_size = @log_file_size
  6245.     --else
  6246.     --  select @max_logfile_size = 16
  6247.  
  6248.     select @createmode_attach = 0, @createmode_noattach = 1, @createmode_fordetach = 2
  6249.     SELECT @trunc_log_bit = 8
  6250.     SELECT @distbit = 16
  6251.  
  6252.     if (@createmode <> @createmode_fordetach)
  6253.     begin
  6254.     
  6255.         /* 
  6256.         ** Check if replication components are installed on this server
  6257.         */
  6258.         exec @retcode = dbo.sp_MS_replication_installed
  6259.         if (@retcode <> 1)
  6260.         begin
  6261.             return (1)
  6262.         end
  6263.     
  6264.         /* 
  6265.         ** Check for invalid security modes
  6266.         */
  6267.         IF @security_mode < 0 OR @security_mode > 1
  6268.         BEGIN
  6269.             RAISERROR(14109, 16, -1)
  6270.             RETURN (1)
  6271.         END
  6272.  
  6273.         IF ( ( @platform_nt != platform() & @platform_nt ) and @security_mode = 1)
  6274.         BEGIN
  6275.             RAISERROR(21038, 16, -1)
  6276.             RETURN (1)
  6277.         END
  6278.     
  6279.         /* 
  6280.         ** Check for invalid retention values 
  6281.         */
  6282.         IF @min_distretention < 0 OR @max_distretention < 0 
  6283.         BEGIN
  6284.             RAISERROR(14106, 16, -1)
  6285.             RETURN (1)
  6286.         END
  6287.         IF @min_distretention > @max_distretention
  6288.         BEGIN
  6289.             RAISERROR(14107, 16, -1) 
  6290.             RETURN (1)
  6291.         END
  6292.  
  6293.         /*
  6294.         ** Check to make sure this is a distributor
  6295.         */
  6296.         IF NOT EXISTS (SELECT * FROM master..sysservers
  6297.               WHERE UPPER(datasource) = UPPER(@@SERVERNAME) collate database_default
  6298.                  AND srvstatus & 8 <> 0)
  6299.         BEGIN
  6300.             RAISERROR (14114, 16, -1, @@SERVERNAME)
  6301.             RETURN(1)
  6302.         END
  6303.     
  6304.         /*
  6305.         ** Check if database is already configured as a distributor database
  6306.         */
  6307.         IF EXISTS (SELECT * FROM msdb..MSdistributiondbs WHERE name = @database collate database_default)
  6308.         BEGIN
  6309.             RAISERROR (14119, 16, -1, @database)
  6310.             RETURN(1)
  6311.         END    
  6312.     end
  6313.  
  6314.     /* 
  6315.     ** Get path to osql client (TOOLS) directory
  6316.     */
  6317.     EXECUTE @retcode = master.dbo.sp_MSgettools_path @osql_path OUTPUT
  6318.     IF ( @retcode <> 0 ) or ( @@ERROR <> 0 ) or ( @osql_path is NULL ) or ( @osql_path = '' )
  6319.     BEGIN
  6320.         GOTO UNDO       
  6321.     END
  6322.  
  6323.     /* 
  6324.     ** Get path to version specific INSTALL directory
  6325.     */
  6326.     exec @retcode = master.dbo.sp_MSget_setup_paths
  6327.         @sql_path = @install_path output,
  6328.         @data_path = @mssql_data_path output
  6329.     IF @retcode <> 0 or @install_path is NULL or @install_path='' or @mssql_data_path = ''
  6330.     BEGIN
  6331.         GOTO UNDO       
  6332.     END
  6333.  
  6334.     IF @data_folder IS NULL or @data_folder = ''
  6335.         select @data_folder = @mssql_data_path + '\DATA'
  6336.  
  6337.     IF @log_folder IS NULL or @log_folder = ''
  6338.         select @log_folder = @mssql_data_path + '\DATA'
  6339.  
  6340.     IF @data_file IS NULL
  6341.         SELECT @data_file = @database + '.MDF'
  6342.  
  6343.     IF @log_file IS NULL
  6344.         SELECT @log_file = @database + '.LDF'
  6345.  
  6346.     if substring(@data_folder, len(@data_folder), 1) = '\'
  6347.     select @data_folder = substring (@data_folder, 1, len(@data_folder) -1)
  6348.     if substring(@log_folder, len(@log_folder), 1) = '\'
  6349.     select @log_folder = substring (@log_folder, 1, len(@log_folder) -1)
  6350.  
  6351.     SELECT @data_path = @data_folder + '\' + @data_file
  6352.     SELECT @log_path = @log_folder + '\' + @log_file
  6353.  
  6354.     SELECT @data_path_quoted_for_copy = '"' + fn_escapecmdshellsymbolsremovequotes(@data_folder) collate database_default + '\' + fn_escapecmdshellsymbolsremovequotes(@data_file) collate database_default + '"'
  6355.     SELECT @log_path_quoted_for_copy = '"' + fn_escapecmdshellsymbolsremovequotes(@log_folder) collate database_default + '\' + fn_escapecmdshellsymbolsremovequotes(@log_file) collate database_default + '"'
  6356.  
  6357.     select @logical_data_file = @database
  6358.  
  6359.     /* 
  6360.     ** Truncate the logical log file name back to 128 characters
  6361.     ** long so the 'CREATE DATABASE' statement won't complain.
  6362.     */
  6363.     /* LEN(@logical_log_file) = LEN(@database) + LEN('_log') and
  6364.        LEN(@logical_log_file) <= 128 implies 
  6365.        LEN(@database) <=124 */
  6366.     IF (LEN(@database) > 124)
  6367.         SELECT @logical_log_file = SUBSTRING(@database, 1, 124) + '_log'  
  6368.     ELSE 
  6369.         SELECT @logical_log_file = @database + '_log'
  6370.  
  6371.     if (@createmode = @createmode_attach)
  6372.     begin
  6373.         select @canneddbdata_file = @mssql_data_path + '\DATA\DISTMDL.MDF'
  6374.         select @canneddblog_file = @mssql_data_path + '\DATA\DISTMDL.LDF'
  6375.  
  6376.         exec dbo.sp_MSget_file_existence @canneddbdata_file, @file_exists OUTPUT
  6377.         if (@file_exists = 0)
  6378.         begin
  6379.             /* Fallback to mode where instdist.sql needs to be run */
  6380.             select @createmode = @createmode_noattach
  6381.         end
  6382.  
  6383.         exec dbo.sp_MSget_file_existence @canneddblog_file, @file_exists OUTPUT
  6384.         if (@file_exists = 0)
  6385.         begin
  6386.             /* Fallback to mode where instdist.sql needs to be run */
  6387.             select @createmode = @createmode_noattach
  6388.         end
  6389.     end
  6390.  
  6391.     /*
  6392.     ** Create the distributor database if it does not exist
  6393.     */
  6394.     IF NOT EXISTS (SELECT * from master..sysdatabases WHERE name = @database collate database_default) AND (@createmode <> @createmode_attach)
  6395.     BEGIN
  6396.  
  6397.         -- Note: Use system's default file growth.
  6398.         IF @logical_data_file IS NOT NULL AND NOT EXISTS (SELECT * FROM master..sysdevices WHERE name = @logical_data_file collate database_default)
  6399.         BEGIN
  6400.             SELECT @on_clause = ' ON (NAME =''' + @logical_data_file + ''',FILENAME=''' + REPLACE( @data_path, '''', '''''' ) + 
  6401.                 ''', SIZE=' + @data_file_size_str + ', MAXSIZE = UNLIMITED)'
  6402.         END
  6403.  
  6404.         IF @logical_log_file IS NOT NULL AND NOT EXISTS (SELECT * FROM master..sysdevices WHERE name = @logical_log_file collate database_default)
  6405.         BEGIN
  6406.             SELECT @logon_clause = ' LOG ON (NAME =''' + @logical_log_file + ''',FILENAME=''' + REPLACE( @log_path, '''', '''''' ) + 
  6407.                 ''', SIZE=' + @log_file_size_str + ', MAXSIZE= UNLIMITED)'          
  6408.         END
  6409.  
  6410.         /*
  6411.         ** Create distributor database
  6412.         */
  6413.         SELECT @command = 'USE master  CREATE DATABASE ' +  QUOTENAME(@database) + 
  6414.             + isnull(@on_clause, ' ') + isnull(@logon_clause, ' ')
  6415.  
  6416.         EXEC (@command)
  6417.         IF @@ERROR <> 0
  6418.             RETURN (1)
  6419.         SELECT @db_exists = 0
  6420.     END
  6421.     ELSE IF NOT EXISTS (SELECT * from master..sysdatabases WHERE name = @database collate database_default) AND (@createmode = @createmode_attach)
  6422.     BEGIN
  6423.     /* DO THE CREATE DATABASE FOR ATTACH STUFF */
  6424.         
  6425.         exec dbo.sp_MSget_file_existence @data_path, @data_file_preexists OUTPUT
  6426.         if (@data_file_preexists = 1)
  6427.         begin
  6428.             raiserror(5170, 16, -1, @data_path)
  6429.             return 1
  6430.         end
  6431.     
  6432.         SELECT @on_clause = ' ON (NAME = ''' + @logical_data_file + ''', FILENAME=''' + REPLACE( @data_path, '''', '''''' ) + ''')'
  6433.         
  6434.         exec dbo.sp_MSget_file_existence @log_path, @log_file_preexists OUTPUT
  6435.         if (@log_file_preexists = 1)
  6436.         begin
  6437.             raiserror(5170, 16, -1, @log_path)
  6438.             return 1
  6439.         end
  6440.  
  6441.         SELECT @logon_clause = ' LOG ON (NAME = ''' + @logical_log_file + ''', FILENAME=''' + REPLACE( @log_path, '''', '''''' ) + ''')'
  6442.  
  6443.         select @filecopy_cmd = 'copy "' + fn_escapecmdshellsymbolsremovequotes(@canneddbdata_file) collate database_default + '" ' + @data_path_quoted_for_copy
  6444.         EXEC @retcode = master..xp_cmdshell @filecopy_cmd, NO_OUTPUT
  6445.         IF @retcode <> 0 OR @@ERROR <> 0
  6446.         BEGIN
  6447.             RAISERROR (14113, 16, -1, @filecopy_cmd, 'instdist.out')
  6448.             return (1)
  6449.         END
  6450.  
  6451.         select @filecopy_cmd = 'copy "' + fn_escapecmdshellsymbolsremovequotes(@canneddblog_file) collate database_default + '" ' + @log_path_quoted_for_copy
  6452.         EXEC @retcode = master..xp_cmdshell @filecopy_cmd, NO_OUTPUT
  6453.         IF @retcode <> 0 OR @@ERROR <> 0
  6454.         BEGIN
  6455.             RAISERROR (14113, 16, -1, @filecopy_cmd, 'instdist.out')
  6456.             return (1)
  6457.         END
  6458.  
  6459.         /*
  6460.         ** Create distributor database
  6461.         */
  6462.         SELECT @command = 'USE master  CREATE DATABASE ' +  QUOTENAME(@database) + 
  6463.             + @on_clause + @logon_clause + ' FOR ATTACH'
  6464.  
  6465.         EXEC (@command)
  6466.         IF @@ERROR <> 0
  6467.         begin
  6468.             RETURN (1)
  6469.         end
  6470.         dbcc dbreindexall(@database, 240) with no_infomsgs
  6471.  
  6472.         SELECT @db_exists = 0
  6473.     END
  6474.     ELSE
  6475.     BEGIN
  6476.         SELECT @db_exists = 1
  6477.     END
  6478.  
  6479.     -- Must make the dist db owned by sa so that the sps in it can select from
  6480.     -- security cache tables in tempdb by owership chain rule.
  6481.     declare @retcode2 int
  6482.     select @retcode2 = 0
  6483.     select @distproc = QUOTENAME(@database) + '.dbo.sp_executesql'
  6484.     SELECT @command = 
  6485.         -- If the db is created by sa or from attach, sa is dbo already.
  6486.         -- sp_changedbowner will fail is the new owner is an user in the db already.
  6487.         ' if not exists (select * from sysusers where sid = 0x01) ' +
  6488.         ' exec @retcode2 = dbo.sp_changedbowner ''sa'''
  6489.     EXEC @retcode = @distproc @command, N'@retcode2 int output', @retcode2 output
  6490.     IF @retcode <> 0 or @retcode2 <> 0 or @@ERROR <> 0
  6491.     BEGIN
  6492.         GOTO UNDO
  6493.     END
  6494.  
  6495.     /* Set the database option truncate log on checkpoint & turn off autoclose which is default of win9x*/
  6496.     IF EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE 
  6497.         name = @database collate database_default AND
  6498.         (status & @trunc_log_bit) = 0 )   -- if its not already marked
  6499.     BEGIN
  6500.         EXEC @retcode = dbo.sp_dboption @database, 'trunc. log on chkpt.', 'true'
  6501.         IF @retcode <> 0 OR @@ERROR <> 0
  6502.         BEGIN
  6503.             GOTO UNDO
  6504.         END
  6505.     END
  6506.  
  6507.     EXEC @retcode = dbo.sp_dboption @database, 'autoclose', 'false'
  6508.         IF @retcode <> 0 OR @@ERROR <> 0
  6509.         BEGIN
  6510.             GOTO UNDO
  6511.         END
  6512.  
  6513.     /*
  6514.     **
  6515.     ** Update sysdatabase category bit
  6516.     ** This is to prevent user from dropping the database.
  6517.     **/
  6518.     if (@createmode <> @createmode_fordetach)
  6519.     begin
  6520.         UPDATE master..sysdatabases SET category = category | @distbit WHERE name = @database collate database_default
  6521.         IF @@ERROR <> 0
  6522.         BEGIN
  6523.             GOTO UNDO
  6524.         END
  6525.     end
  6526.  
  6527.     /* 
  6528.     ** Install instdist.sql
  6529.     */
  6530.  
  6531.     if (@createmode <> @createmode_attach) OR (@db_exists = 1)
  6532.     begin
  6533.         if (( platform() & @platform_nt = @platform_nt ))
  6534.             select @osql_for_nt = 1
  6535.         else
  6536.             select @osql_for_nt = 0
  6537.  
  6538.         -- Always use integrated security on WINNT since @login passed-in is for remote 
  6539.         -- subscriber and may not have enough privilege to apply the script
  6540.         IF (@security_mode = 1 or @osql_for_nt = 1) AND NOT (@security_mode = 0 AND @createmode = 2)
  6541.         BEGIN
  6542.             SELECT @osql_cmd = '" "' + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -E '  
  6543.             if serverproperty('instancename') is not null
  6544.                 SELECT @osql_cmd = @osql_cmd + ' -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" '
  6545.         END
  6546.         ELSE
  6547.         BEGIN
  6548.         -- cannot specify -S w/ -E for local execution, SID does not map 
  6549.         if (@osql_for_nt = 1)
  6550.             SELECT @osql_cmd = '" "' + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -U"' + fn_escapecmdshellsymbols(@login) collate database_default + '" -P"' + 
  6551.                 fn_escapecmdshellsymbols(isnull(@password,'')) collate database_default + '" -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" '
  6552.         else
  6553.             SELECT @osql_cmd = '"'   + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -U"' + fn_escapecmdshellsymbols(@login) collate database_default + '" -P"' + 
  6554.                 fn_escapecmdshellsymbols(isnull(@password,'')) collate database_default + '" -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" '
  6555.         END
  6556.     
  6557.         select @osql_cmd = @osql_cmd + '-l60 -t60 '
  6558.  
  6559.         -- We must use -b option to make osql return error code !!
  6560.         SELECT @osql_cmd = @osql_cmd + 
  6561.             ' -d"' + fn_escapecmdshellsymbols(@database) collate database_default + '" -b ' +
  6562.             ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\instdist.sql"' + 
  6563.             ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\instdist.out"'
  6564.  
  6565.         if (@osql_for_nt = 1)
  6566.         BEGIN
  6567.             SELECT @osql_cmd = @osql_cmd + ' "'
  6568.         END
  6569.     
  6570.         EXEC @retcode = master..xp_cmdshell @osql_cmd
  6571.         IF @retcode <> 0 OR @@ERROR <> 0
  6572.         BEGIN
  6573.             RAISERROR (14113, 16, -1, @osql_cmd, 'instdist.out')
  6574.             GOTO UNDO       
  6575.         END
  6576.     end
  6577.     
  6578.     if (@createmode <> @createmode_fordetach)
  6579.     begin
  6580.         /* Set db_existed bit in MSrepl_version */
  6581.         IF @db_exists = 1
  6582.         BEGIN
  6583.             SELECT @distproc = 'UPDATE ' +
  6584.                 @database + '..MSrepl_version SET db_existed = 0x1'
  6585.     
  6586.             EXEC(@distproc)
  6587.             IF @@ERROR <> 0
  6588.             BEGIN
  6589.                 GOTO UNDO       
  6590.             END
  6591.         END
  6592.  
  6593.         DELETE msdb.dbo.MSdistributiondbs WHERE name = @database collate database_default
  6594.         IF @@ERROR <> 0
  6595.         BEGIN
  6596.             GOTO UNDO       
  6597.         END
  6598.  
  6599.         INSERT INTO msdb.dbo.MSdistributiondbs VALUES (
  6600.             @database, @min_distretention, @max_distretention, @history_retention
  6601.             )
  6602.         IF @@ERROR <> 0
  6603.         BEGIN
  6604.             GOTO UNDO       
  6605.         END
  6606.  
  6607.         -- This login need db_owner priviledge to call sps in distribution db
  6608.         declare @distributor_login sysname
  6609.         select @distributor_login = 'distributor_admin'
  6610.  
  6611.         select @command = quotename(@database) + '.dbo.sp_MSrepl_dbrole'
  6612.         exec @retcode = @command 'db_owner', @distributor_login, 'add'
  6613.         IF @@error <> 0 OR @retcode <> 0
  6614.             GOTO UNDO
  6615.  
  6616.         if @from_scripting = 0
  6617.         begin
  6618.             /*
  6619.             ** Create the history cleanup agent.
  6620.             */
  6621.             SELECT @agentname = formatmessage (20567, @database)
  6622.             SELECT @command =  'EXEC dbo.sp_MShistory_cleanup @history_retention = ' + 
  6623.                 CONVERT(nvarchar(12), @history_retention)
  6624.  
  6625.             IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE name = @agentname collate database_default and
  6626.                 UPPER(originating_server) = UPPER(CONVERT(sysname, SERVERPROPERTY('ServerName'))))
  6627.             BEGIN
  6628.                 EXEC @retcode = msdb.dbo.sp_delete_job 
  6629.                     @job_name = @agentname
  6630.                 IF @@ERROR <> 0 or @retcode <> 0
  6631.                 BEGIN
  6632.                     GOTO UNDO
  6633.                 END
  6634.             END
  6635.  
  6636.             set @description = formatmessage(20535)
  6637.  
  6638.             -- Get History Cleanup category name (assumes category_id = 12)
  6639.             select @category_name = name FROM msdb.dbo.syscategories where category_id = 12
  6640.  
  6641.             EXECUTE @retcode = dbo.sp_MSadd_repl_job @agentname,
  6642.             @subsystem = 'TSQL',
  6643.             @server = @@SERVERNAME,
  6644.             @databasename = @database,
  6645.             @description = @description,
  6646.             @freqtype = 4,    
  6647.             @freqsubtype = 4,         
  6648.             @freqsubinterval = 10,    /* Number of minutes between runs */ 
  6649.             @command = @command,
  6650.             @enabled = 1,
  6651.             @retryattempts = 0,
  6652.             @loghistcompletionlevel = 0,
  6653.             @category_name = @category_name
  6654.     
  6655.             IF @@ERROR <> 0 or @retcode <> 0
  6656.             BEGIN
  6657.                 GOTO UNDO
  6658.             END
  6659.  
  6660.             /*
  6661.             ** Create the distribution cleanup agent.
  6662.             */
  6663.             SELECT @agentname = formatmessage (20568, @database)
  6664.             SELECT @command =  'EXEC dbo.sp_MSdistribution_cleanup @min_distretention = ' + 
  6665.                 CONVERT(nvarchar(12), @min_distretention) + ', @max_distretention = ' +
  6666.                 CONVERT(nvarchar(12), @max_distretention)
  6667.  
  6668.             IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE name = @agentname collate database_default and
  6669.                 UPPER(originating_server) = UPPER(CONVERT(sysname, SERVERPROPERTY('ServerName'))))
  6670.             BEGIN
  6671.                 EXEC @retcode = msdb.dbo.sp_delete_job 
  6672.                     @job_name = @agentname
  6673.                 IF @@ERROR <> 0 or @retcode <> 0
  6674.                 BEGIN
  6675.                     GOTO UNDO
  6676.                 END
  6677.             END
  6678.  
  6679.             set @description = formatmessage(20541)
  6680.             -- Get Distribution Cleanup category name (assumes category_id = 11)
  6681.             select @category_name = name FROM msdb.dbo.syscategories where category_id = 11
  6682.     
  6683.             EXECUTE @retcode = msdb.dbo.sp_MSadd_repl_job @agentname,
  6684.             @subsystem = 'TSQL',
  6685.             @server = @@SERVERNAME,
  6686.             @databasename = @database,
  6687.             @description = @description,
  6688.             @freqtype = 4,    
  6689.             @freqsubtype = 4,         
  6690.             @freqsubinterval = 10,    /* Number of minutes between runs */ 
  6691.             @command = @command,
  6692.             @retryattempts = 0,
  6693.             @enabled = 0,
  6694.             @loghistcompletionlevel = 0,
  6695.             @category_name = @category_name,
  6696.             -- Start  and end time is 5 min off from the history cleanup, which use the default.
  6697.             @activestarttimeofday = 000500,
  6698.             @activeendtimeofday   = 000459
  6699.  
  6700.             IF @@ERROR <> 0 or @retcode <> 0
  6701.             BEGIN
  6702.                 GOTO UNDO
  6703.             end
  6704.         end
  6705.     end
  6706.     else
  6707.     begin
  6708.         /*detach */
  6709.         dbcc detachdb(@database)
  6710.     end
  6711.     
  6712.     RETURN(0)
  6713.  
  6714. UNDO:
  6715.  
  6716.     IF @db_exists = 0
  6717.         EXECUTE dbo.sp_dropdistributiondb @database
  6718.  
  6719.     /* Need to do it since sp_dropdistributiondb will fail in some cases */
  6720.     UPDATE master..sysdatabases SET category = category & ~@distbit WHERE name = @database collate database_default
  6721.     
  6722.     DELETE msdb.dbo.MSdistributiondbs where name = @database collate database_default
  6723.  
  6724.     /* drop the database and ignore error */
  6725.     IF @db_exists = 0 AND
  6726.         EXISTS (SELECT * from master..sysdatabases WHERE name = @database collate database_default)
  6727.     BEGIN
  6728.         SELECT @command = 'USE master  DROP DATABASE ' +  QUOTENAME(@database) 
  6729.         EXEC (@command)
  6730.     END
  6731.  
  6732.     if (@createmode = @createmode_attach)
  6733.     begin
  6734.         if (@data_file_preexists = 0)
  6735.         begin
  6736.             select @command = 'del ' + @data_path_quoted_for_copy
  6737.             exec master..xp_cmdshell @command
  6738.             --ignore errors
  6739.         end
  6740.         if (@log_file_preexists = 0)
  6741.         begin
  6742.             select @command = 'del ' + @log_path_quoted_for_copy
  6743.             exec master..xp_cmdshell @command
  6744.             --ignore errors
  6745.         end
  6746.     end
  6747.         
  6748.     RETURN(1)        
  6749. GO
  6750.  
  6751. --------------------------------------------------------------------------------
  6752. --. sp_adddistpublisher
  6753. --------------------------------------------------------------------------------
  6754. if exists (select * from sysobjects
  6755.     where type = 'P' and name = 'sp_adddistpublisher')
  6756. drop procedure sp_adddistpublisher
  6757. go
  6758. raiserror('Creating procedure sp_adddistpublisher', 0,1)
  6759. go
  6760.  
  6761. CREATE PROCEDURE sp_adddistpublisher (
  6762.     @publisher sysname,      /* publisher server name */
  6763.     @distribution_db sysname,
  6764.     @security_mode int = NULL,
  6765.     @login sysname = 'sa',
  6766.     @password sysname = NULL,
  6767.     @working_directory nvarchar(255),
  6768.     @trusted nvarchar(5) = NULL,
  6769.     @encrypted_password bit = 0,
  6770.     @thirdparty_flag bit = 0
  6771.         ) AS
  6772.  
  6773.     SET NOCOUNT ON
  6774.  
  6775.     /*
  6776.     ** Declarations.
  6777.     */
  6778.  
  6779.     DECLARE @retcode int
  6780.     DECLARE @reg_key nvarchar(255)
  6781.     DECLARE @distbit int
  6782.     DECLARE @active_value int
  6783.     DECLARE @server_added bit
  6784.     DECLARE @proc nvarchar(255)
  6785.     declare @fExists int
  6786.     declare @command nvarchar(255)
  6787.     declare @trusted_id bit
  6788.     declare @platform_nt binary
  6789.     declare @qv_replication varchar(10)
  6790.     declare @qv_replication_unlimited integer
  6791.     declare @qv_value_replication integer
  6792.     declare @enc_password nvarchar(524)
  6793.  
  6794.     select @platform_nt = 0x1
  6795.     select @qv_replication = '2745196162', @qv_replication_unlimited = 0
  6796.  
  6797.     SELECT @distbit = 16
  6798.     SELECT @server_added = 0
  6799.  
  6800.     /* 
  6801.     ** Check if replication components are installed on this server
  6802.     */
  6803.     exec @retcode = dbo.sp_MS_replication_installed
  6804.     if (@retcode <> 1)
  6805.     begin
  6806.         return (1)
  6807.     end
  6808.  
  6809.     IF @working_directory IS NULL or ltrim(rtrim(@working_directory)) = ''
  6810.     BEGIN
  6811.         RAISERROR (14043, 16, -1, '@working_directory')
  6812.         return (1)
  6813.     END
  6814.  
  6815.  
  6816.     /*
  6817.     ** Parameter Check:  @publisher.
  6818.     ** Check to make sure that the publisher is not NULL and that it
  6819.     ** conforms to the rules for identifiers.
  6820.     */
  6821.  
  6822.     IF @publisher IS NULL
  6823.         BEGIN
  6824.             RAISERROR (14043, 16, -1, '@publisher')
  6825.             return (1)
  6826.         END
  6827.  
  6828.     EXECUTE @retcode = dbo.sp_validname @publisher
  6829.  
  6830.     IF @@ERROR <> 0 OR @retcode <> 0
  6831.         return (1)
  6832.  
  6833.     IF @password = N''
  6834.         select @password = NULL
  6835.  
  6836.     /* On REPLICATION_LIMITED server, only local publisher is supported.
  6837.      * Note: The login and password registered for local publisher will be used for 
  6838.      * local agents to login to distributor, thus local publisher has to be installed first.
  6839.      * We choose not to support remote dist publshers on REPLICATION_LIMITED server altogether.
  6840.      * On NT, local agents will always use integrated security to log into 
  6841.      * distributor
  6842.      * Today, REPLICATION_LIMITED means desktop but we check specific sku entry just in case
  6843.     */
  6844.     exec @qv_value_replication = master.dbo.sp_MSinstance_qv @qv_replication    
  6845.  
  6846.     if ( @qv_value_replication != @qv_replication_unlimited ) and ( UPPER(@publisher) <> UPPER(@@servername) )
  6847.     begin
  6848.         -- remote dist publisher is not supported on this server version
  6849.         raiserror(21041,16,-1)
  6850.         return (1)
  6851.     end
  6852.  
  6853.  
  6854.     -- Set default security
  6855.     IF @security_mode IS NULL
  6856.     BEGIN
  6857.         IF (UPPER(@publisher) = UPPER(@@SERVERNAME) and ( platform() & @platform_nt = @platform_nt ) )
  6858.             SELECT @security_mode = 1
  6859.         ELSE
  6860.             SELECT @security_mode = 0
  6861.     END
  6862.  
  6863.     /* 
  6864.     ** Check for invalid security mode
  6865.     */
  6866.     IF @security_mode < 0 OR @security_mode > 1
  6867.         BEGIN
  6868.             RAISERROR(14109, 16, -1)
  6869.             return (1)
  6870.         END
  6871.  
  6872.     IF (UPPER(@publisher) = UPPER(@@SERVERNAME) and ( @platform_nt != platform() & @platform_nt ) and @security_mode = 1)
  6873.     BEGIN
  6874.         RAISERROR(21038, 16, -1)
  6875.         RETURN (1)
  6876.     END
  6877.  
  6878.     -- Encrypt the password
  6879.     select @enc_password = @password
  6880.     IF @encrypted_password = 0
  6881.     BEGIN
  6882.         EXEC @retcode = master.dbo.xp_repl_encrypt @enc_password OUTPUT
  6883.         IF @@error <> 0 OR @retcode <> 0
  6884.             return 1
  6885.     END
  6886.  
  6887.     -- Validate the working directory 
  6888.     -- Remove heading and trailing spaces
  6889.     select @working_directory = RTRIM(LTRIM(@working_directory))
  6890.     
  6891.     -- if the last char is '\', remove it.
  6892.     if substring(@working_directory, len(@working_directory),1) = '\'
  6893.         select @working_directory = substring(@working_directory, 1,
  6894.             len(@working_directory)-1)
  6895.  
  6896.     -- Don't do validation if it is a UNC path due to security problem.
  6897.     -- If the server is started as a service using local system account, we
  6898.     -- don't have access to the UNC path.
  6899.     if substring(@working_directory, 1,2) <> '\\'
  6900.     begin
  6901.         select @command = 'dir "' + fn_escapecmdshellsymbolsremovequotes(@working_directory) collate database_default + '"'
  6902.         exec @retcode = master..xp_cmdshell @command, 'no_output'
  6903.         if @@error <> 0
  6904.             return (1)
  6905.         if @retcode <> 0 
  6906.         begin
  6907.             raiserror (21037, 16, -1, @working_directory)
  6908.             return (1)
  6909.         end
  6910.     end
  6911.  
  6912.     /*
  6913.     ** Parameter Check:  @trusted
  6914.     */
  6915.  
  6916.     if @trusted is null
  6917.     begin
  6918.         if UPPER(@publisher) = UPPER(@@servername)
  6919.             select @trusted = 'false'
  6920.         else
  6921.             select @trusted = 'true'
  6922.     end
  6923.  
  6924.     IF LOWER(@trusted collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  6925.         BEGIN
  6926.             RAISERROR (14148, 16, -1, '@trusted')
  6927.             RETURN (1)
  6928.         END
  6929.  
  6930.     IF LOWER(@trusted collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @trusted_id = 1
  6931.     ELSE SELECT @trusted_id = 0
  6932.  
  6933.     /*
  6934.     ** Check to make sure this is a distributor
  6935.     */
  6936.     IF NOT EXISTS (SELECT * FROM master..sysservers
  6937.               WHERE UPPER(datasource) = UPPER(@@SERVERNAME) collate database_default
  6938.                  AND srvstatus & 8 <> 0)
  6939.     BEGIN
  6940.         RAISERROR (14114, 16, -1, @@SERVERNAME)
  6941.         return (1)
  6942.     END
  6943.  
  6944.     /*
  6945.     ** Check if database is configured as a distributor database
  6946.     */
  6947.     IF NOT EXISTS (SELECT * FROM msdb..MSdistributiondbs WHERE name = @distribution_db collate database_default)
  6948.     BEGIN
  6949.         RAISERROR (14117, 16, -1, @distribution_db)
  6950.         return (1)
  6951.     END
  6952.  
  6953.     /* Check if publisher is already defined. */
  6954.     IF EXISTS (SELECT *
  6955.          FROM msdb..MSdistpublishers
  6956.         WHERE UPPER(name) = UPPER(@publisher) collate database_default)
  6957.  
  6958.     BEGIN
  6959.         RAISERROR (14074, 16, -1, @publisher)
  6960.         RETURN (1)
  6961.     END
  6962.  
  6963.  
  6964.  
  6965.     IF NOT EXISTS (SELECT *
  6966.              FROM master..sysservers
  6967.             WHERE UPPER(srvname) = UPPER(@publisher) collate database_default)
  6968.  
  6969.     /* Add the server if it does not exist. */
  6970.     BEGIN
  6971.         EXECUTE @retcode = dbo.sp_addserver @publisher
  6972.         IF @@error <> 0 OR @retcode <> 0
  6973.         BEGIN
  6974.             RAISERROR (14075, 16, -1)
  6975.             GOTO UNDO
  6976.         END
  6977.         SELECT @server_added = 1
  6978.     END
  6979.     ELSE
  6980.     BEGIN
  6981.         SELECT @publisher = fn_getpersistedservernamecasevariation(@publisher) collate database_default
  6982.     END
  6983.      
  6984.     /*
  6985.     ** Set the Active  value.
  6986.     ** If the @publisher is local, set it to true.
  6987.     ** Otherwise, set it to false
  6988.     */
  6989.     IF UPPER(@publisher) = UPPER(@@SERVERNAME)
  6990.         SELECT @active_value = 1
  6991.     ELSE
  6992.         SELECT @active_value = 0
  6993.  
  6994.  
  6995.     DELETE msdb.dbo.MSdistpublishers where UPPER(name) = UPPER(@publisher) collate database_default
  6996.     IF @@ERROR <> 0
  6997.     BEGIN
  6998.         GOTO UNDO       
  6999.     END
  7000.  
  7001.     INSERT INTO msdb.dbo.MSdistpublishers VALUES (
  7002.         @publisher, @distribution_db, @working_directory,
  7003.         @security_mode, @login, @enc_password, @active_value, @trusted_id, @thirdparty_flag)
  7004.     IF @@ERROR <> 0
  7005.     BEGIN
  7006.         GOTO UNDO       
  7007.     END
  7008.  
  7009.     -- Add distributor_admin to distribution_admin non trusted mapping
  7010.     exec @fExists = dbo.sp_MSIfExistsRemoteLogin @publisher, null, 
  7011.         'distributor_admin'
  7012.     if( @fExists = 0 )
  7013.     BEGIN
  7014.  
  7015.         EXECUTE @retcode = dbo.sp_addremotelogin @publisher, 'distributor_admin', 
  7016.             'distributor_admin'
  7017.         IF @@error <> 0 OR @retcode <> 0
  7018.         BEGIN
  7019.             RAISERROR (14075, 16, -1)
  7020.             GOTO UNDO
  7021.         END
  7022.     END
  7023.  
  7024.     -- For 6x publisher, we still need the trusted sa to sa.
  7025.     -- For 6x publisher upgrading to 7.0, distributor_admin to distributor_admin need to be trusted.
  7026.     -- add remotelogin of SA if it doesn't already exist
  7027.     -- If there's a mapping for remote login sa already, we cannot map it to distributor_admin
  7028.     -- this is the case of server upgraded from 6.5.
  7029.     exec @fExists = dbo.sp_MSIfExistsRemoteLogin @publisher, null, 'sa'
  7030.     if( @fExists = 0 )
  7031.     BEGIN
  7032.         EXECUTE @retcode = dbo.sp_addremotelogin @publisher, 'distributor_admin', 'sa'
  7033.         IF @@error <> 0 OR @retcode <> 0
  7034.         BEGIN
  7035.             RAISERROR (14075, 16, -1)
  7036.             GOTO UNDO
  7037.         END
  7038.     END
  7039.     if @trusted_id = 1
  7040.     begin
  7041.         exec @fExists = dbo.sp_MSIfExistsRemoteLogin @publisher, 'distributor_admin', 'sa'
  7042.         if( @fExists = 1 )
  7043.         BEGIN
  7044.             EXECUTE @retcode = dbo.sp_remoteoption @publisher, 'distributor_admin', 'sa', trusted, true
  7045.             IF @@error <> 0 OR @retcode <> 0
  7046.             BEGIN
  7047.                 RAISERROR (14075, 16, -1)
  7048.                 GOTO UNDO
  7049.             END
  7050.         END
  7051.  
  7052.         EXECUTE @retcode = dbo.sp_remoteoption @publisher, 'distributor_admin', 'distributor_admin', trusted, true
  7053.         IF @@error <> 0 OR @retcode <> 0
  7054.         BEGIN
  7055.             RAISERROR (14075, 16, -1)
  7056.             GOTO UNDO
  7057.         END
  7058.     END
  7059.  
  7060.  
  7061.     /* Add remotelogin enabling the 'probe' of the publisher to
  7062.     ** RPC for distribution counter information.
  7063.     */
  7064. /* SECURITY ********************************
  7065.     IF NOT EXISTS (SELECT *
  7066.               FROM master..sysremotelogins srl,
  7067.                master..sysservers ss
  7068.              WHERE UPPER(ss.srvname) = UPPER(@publisher) collate database_default
  7069.            AND srl.remoteserverid = ss.srvid
  7070.            AND srl.remoteusername = 'probe'
  7071.        AND srl.suid = 10)    -- 'probe' 
  7072.     exec @fExists = dbo.sp_MSIfExistsRemoteLogin @publisher, 'probe', 'probe'
  7073.     if (@fExists = 0)
  7074.     BEGIN
  7075.        EXECUTE @retcode = dbo.sp_addremotelogin @publisher, 'probe', 'probe'
  7076.        IF @@error <> 0 OR @retcode <> 0
  7077.        BEGIN
  7078.         RAISERROR (14075, 16, -1)
  7079.         GOTO UNDO
  7080.        END
  7081.     END
  7082. *********************************/
  7083.     
  7084.     RETURN(0)
  7085.  
  7086. UNDO:
  7087.     -- If the server is marked, drop it
  7088.     IF EXISTS (SELECT *
  7089.          FROM msdb..MSdistpublishers
  7090.         WHERE UPPER(name) = UPPER(@publisher) collate database_default)
  7091.         EXEC dbo.sp_dropdistpublisher @publisher
  7092.  
  7093.     IF @server_added = 1
  7094.         EXEC dbo.sp_dropserver @publisher
  7095.  
  7096.     RETURN(1)
  7097. GO
  7098.  
  7099. --------------------------------------------------------------------------------
  7100. --. sp_changedistpublisher
  7101. --------------------------------------------------------------------------------
  7102. if exists (select * from sysobjects
  7103.     where type = 'P' and name = 'sp_changedistpublisher')
  7104. drop procedure sp_changedistpublisher
  7105. go
  7106. raiserror('Creating procedure sp_changedistpublisher', 0,1)
  7107. go
  7108.  
  7109. CREATE PROCEDURE sp_changedistpublisher (
  7110.     @publisher sysname,
  7111.     @property sysname     = NULL,     /* The property to change */
  7112.     @value nvarchar(255)     = NULL      /* The new property value */
  7113.     ) AS
  7114.  
  7115.     SET NOCOUNT ON
  7116.  
  7117.     /*
  7118.     ** Declarations.
  7119.     */
  7120.     DECLARE @retcode int
  7121.     DECLARE @new_database sysname
  7122.     DECLARE @new_security_mode int
  7123.     DECLARE @new_login sysname
  7124.     DECLARE @new_password nvarchar(524)
  7125.     DECLARE @distbit int
  7126.     DECLARE @new_active int
  7127.     DECLARE @new_trusted bit
  7128.     DECLARE @command nvarchar(255)
  7129.     declare @distribdb sysname
  7130.     DECLARE @platform_nt binary
  7131.  
  7132.     SELECT @platform_nt = 0x1
  7133.     SELECT @distbit = 16
  7134.     
  7135.     /*
  7136.     ** Parameter Check:  @property.
  7137.     ** If the @property parameter is NULL, print the options.
  7138.     */
  7139.  
  7140.     IF @property IS NULL
  7141.         BEGIN
  7142.             CREATE TABLE #tab1 (properties sysname collate database_default not null)
  7143.             INSERT INTO #tab1 VALUES ('distribution_db')
  7144.             INSERT INTO #tab1 VALUES ('working_directory')
  7145.             INSERT INTO #tab1 VALUES ('security_mode')
  7146.             INSERT INTO #tab1 VALUES ('login')
  7147.             INSERT INTO #tab1 VALUES ('password')
  7148.             INSERT INTO #tab1 VALUES ('active')
  7149.             INSERT INTO #tab1 VALUES ('trusted')
  7150.             SELECT * FROM #tab1
  7151.             RETURN (0)
  7152.         END
  7153.  
  7154.     /*
  7155.     ** Parameter Check:  @property.
  7156.     ** Check to make sure that @property is a valid property in
  7157.     ** msdb.dbo.MSdistpublishers.
  7158.     */
  7159.     IF @property IS NULL OR LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) NOT IN 
  7160.         ('distribution_db',
  7161.          'working_directory',
  7162.          'security_mode',
  7163.          'login',
  7164.          'password',
  7165.          'active',
  7166.          'trusted')
  7167.         BEGIN
  7168.             RAISERROR (14115, 16, -1, 
  7169.             '''distribution_db'', ''working_directory'', ''security_mode'', ''login'', ''password'', ''active'', or ''trusted''')
  7170.             RETURN (1)
  7171.         END
  7172.  
  7173.     /*
  7174.     ** Check to make sure this is a distributor
  7175.     */
  7176.     IF NOT EXISTS (SELECT * FROM master..sysservers
  7177.               WHERE UPPER(datasource) = UPPER(@@SERVERNAME) collate database_default
  7178.                  AND srvstatus & 8 <> 0)
  7179.     BEGIN
  7180.         RAISERROR (14114, 16, -1, @@SERVERNAME)
  7181.         RETURN(1)
  7182.     END
  7183.  
  7184.     -- Get the distribution db name.
  7185.     select @distribdb = distribution_db from msdb..MSdistpublishers where
  7186.         UPPER(name) = UPPER(@publisher) collate database_default
  7187.  
  7188.     /*
  7189.     ** Change the property.
  7190.     */
  7191.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'distribution_db'
  7192.         BEGIN
  7193.             IF @value IS NULL
  7194.                 BEGIN
  7195.                     RAISERROR (14043, 16, -1, '@value') 
  7196.                     RETURN (1)
  7197.                 END
  7198.  
  7199.             IF @value <> @distribdb and 
  7200.                 EXISTS (SELECT * FROM msdb.dbo.MSdistpublishers WHERE
  7201.                 UPPER(name) = UPPER(@publisher) collate database_default and active = 1)
  7202.             BEGIN
  7203.                 RAISERROR (21046, 16, -1)
  7204.                 RETURN (1)
  7205.             END
  7206.  
  7207.             /*
  7208.             ** Check if database is configured as a distributor database
  7209.             */
  7210.             IF NOT EXISTS (SELECT * FROM master..sysdatabases
  7211.               WHERE name = @value collate database_default
  7212.                  AND category & @distbit <> 0)
  7213.                 BEGIN
  7214.                     RAISERROR (14117, 16, -1, @new_database)
  7215.                     RETURN(1)
  7216.                 END
  7217.  
  7218.             UPDATE msdb..MSdistpublishers SET distribution_db = @value
  7219.                 WHERE UPPER(name) = UPPER(@publisher) collate database_default
  7220.             IF @@error <> 0 
  7221.                 BEGIN
  7222.                     RETURN (1)
  7223.                 END
  7224.         END
  7225.    
  7226.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'working_directory'
  7227.         BEGIN
  7228.             IF @value IS NULL
  7229.                 BEGIN
  7230.                     RAISERROR (14043, 16, -1, '@value') 
  7231.                     RETURN (1)
  7232.                 END
  7233.  
  7234.             
  7235.             -- Validate the working directory 
  7236.             -- Remove heading and trailing spaces
  7237.             select @value = RTRIM(LTRIM(@value))
  7238.  
  7239.             -- if the last char is '\', remove it.
  7240.  
  7241.             if substring(@value, len(@value),1) = '\'
  7242.                 select @value = substring(@value, 1,
  7243.                     len(@value)-1)
  7244.  
  7245.             -- Don't do validation if it is a UNC path due to security problem.
  7246.             -- If the server is started as a service using local system account, we
  7247.             -- don't have access to the UNC path.
  7248.             if substring(@value, 1,2) <> '\\'
  7249.             begin
  7250.                 select @command = 'dir "' + fn_escapecmdshellsymbolsremovequotes(@value) collate database_default + N'"'
  7251.                 exec @retcode = master..xp_cmdshell @command, 'no_output'
  7252.                 if @@error <> 0
  7253.                     return 1
  7254.                 if @retcode <> 0 
  7255.                 begin
  7256.                     raiserror (21037, 16, -1, @value)
  7257.                     return 1
  7258.                 end
  7259.             end
  7260.  
  7261.             UPDATE msdb..MSdistpublishers SET working_directory = @value
  7262.                 WHERE UPPER(name) = UPPER(@publisher) collate database_default
  7263.             IF @@error <> 0 
  7264.                 BEGIN
  7265.                     RETURN (1)
  7266.                 END
  7267.         END
  7268.  
  7269.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'security_mode'
  7270.         BEGIN
  7271.             IF @value IS NULL
  7272.                 BEGIN
  7273.                     RAISERROR (14043, 16, -1, '@value') 
  7274.                     RETURN (1)
  7275.                 END
  7276.  
  7277.             /*
  7278.             ** Set the SecurityMode registry key value
  7279.             */
  7280.             SELECT @new_security_mode = CONVERT(int, @value)
  7281.  
  7282.             /* 
  7283.             ** Check for invalid values 
  7284.             */
  7285.             IF @new_security_mode < 0 OR @new_security_mode > 1
  7286.                 BEGIN
  7287.                     RAISERROR(14109, 16, -1)
  7288.                     RETURN (1)
  7289.                 END
  7290.  
  7291.             IF (UPPER(@publisher) = UPPER(@@SERVERNAME) and ( @platform_nt != platform() & @platform_nt ) and @new_security_mode = 1)
  7292.             BEGIN
  7293.                 RAISERROR(21038, 16, -1)
  7294.                 RETURN (1)
  7295.             END
  7296.  
  7297.             UPDATE msdb..MSdistpublishers SET security_mode = @new_security_mode
  7298.                 WHERE UPPER(name) = UPPER(@publisher) collate database_default
  7299.             IF @@error <> 0 
  7300.                 BEGIN
  7301.                     RETURN (1)
  7302.                 END
  7303.         END
  7304.  
  7305.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'login'
  7306.         BEGIN
  7307.             IF @value IS NULL
  7308.                 BEGIN
  7309.                     RAISERROR (14043, 16, -1, '@value') 
  7310.                     RETURN (1)
  7311.                 END
  7312.  
  7313.             /*
  7314.             ** Set the Login registry key value
  7315.             */
  7316.             SELECT @new_login = CONVERT(sysname, @value)
  7317.  
  7318.             UPDATE msdb..MSdistpublishers SET login = @new_login
  7319.                 WHERE UPPER(name) = UPPER(@publisher) collate database_default
  7320.             IF @@error <> 0 
  7321.                 BEGIN
  7322.                     RETURN (1)
  7323.                 END
  7324.         END
  7325.  
  7326.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'password'
  7327.         BEGIN
  7328.             /*
  7329.             ** Set the Password registry key value
  7330.             */
  7331.             SELECT @new_password = CONVERT(nvarchar(524), @value)
  7332.  
  7333.             -- Encrypt the password
  7334.             EXEC @retcode = master.dbo.xp_repl_encrypt @new_password OUTPUT
  7335.             IF @@error <> 0 OR @retcode <> 0
  7336.                 RETURN (1)
  7337.  
  7338.             UPDATE msdb..MSdistpublishers SET password = @new_password
  7339.                 WHERE UPPER(name) = UPPER(@publisher) collate database_default
  7340.             IF @@error <> 0 
  7341.                 BEGIN
  7342.                     RETURN (1)
  7343.                 END
  7344.          END
  7345.  
  7346.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'active'
  7347.         BEGIN
  7348.             /*
  7349.             ** Check for a valid  value.
  7350.             */
  7351.  
  7352.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7353.             BEGIN
  7354.                 RAISERROR (14137, 16, -1)
  7355.                 RETURN (1)
  7356.             END
  7357.  
  7358.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  7359.             begin
  7360.                 -- Clean up the database in case of the remote publisher is reinstalling publishing.
  7361.                 SELECT @command = @distribdb + '.dbo.sp_MSdistpublisher_cleanup'
  7362.                 exec @retcode = @command @publisher
  7363.                 if @retcode <> 0 or @@error <> 0
  7364.                     return 1
  7365.                 SELECT @new_active = 1
  7366.             end
  7367.             ELSE
  7368.             BEGIN
  7369.                 SELECT @new_active = 0
  7370.             END
  7371.  
  7372.             /*
  7373.             ** Set the Active registry key value
  7374.             */
  7375.             UPDATE msdb..MSdistpublishers SET active = @new_active
  7376.                 WHERE UPPER(name) = UPPER(@publisher) collate database_default
  7377.             IF @@error <> 0
  7378.                 BEGIN
  7379.                     RETURN (1)
  7380.                 END
  7381.  
  7382.         END
  7383.  
  7384.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'trusted'
  7385.         BEGIN
  7386.             /*
  7387.             ** Check for a valid  value.
  7388.             */
  7389.  
  7390.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  7391.             BEGIN
  7392.                 RAISERROR (14137, 16, -1)
  7393.                 RETURN (1)
  7394.             END
  7395.  
  7396.             declare @fExists int
  7397.  
  7398.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  7399.             begin
  7400.                 SELECT @new_trusted = 1
  7401.                 exec @fExists = dbo.sp_MSIfExistsRemoteLogin @publisher, 'distributor_admin', 'sa'
  7402.                 if( @fExists = 1 )
  7403.                 BEGIN
  7404.                     EXECUTE @retcode = dbo.sp_remoteoption @publisher, 'distributor_admin', 'sa', trusted, true
  7405.                     IF @@error <> 0 OR @retcode <> 0
  7406.                     BEGIN
  7407.                         RAISERROR (14075, 16, -1)
  7408.                         RETURN (1)
  7409.                     END
  7410.                 END
  7411.  
  7412.  
  7413.                 EXECUTE @retcode = dbo.sp_remoteoption @publisher, 'distributor_admin', 
  7414.                     'distributor_admin', trusted, true
  7415.                 IF @@error <> 0 OR @retcode <> 0
  7416.                 BEGIN
  7417.                     RAISERROR (14075, 16, -1)
  7418.                     RETURN (1)
  7419.                 END
  7420.             end
  7421.             ELSE
  7422.             BEGIN
  7423.                 SELECT @new_trusted = 0
  7424.      
  7425.                 exec @fExists = dbo.sp_MSIfExistsRemoteLogin @publisher, 'distributor_admin', 'sa'
  7426.                 if( @fExists = 1 )
  7427.                 BEGIN
  7428.                     EXECUTE @retcode = dbo.sp_remoteoption @publisher, 'distributor_admin', 'sa', trusted, false
  7429.                     IF @@error <> 0 OR @retcode <> 0
  7430.                     BEGIN
  7431.                         RAISERROR (14075, 16, -1)
  7432.                         RETURN (1)
  7433.                     END
  7434.                 END
  7435.  
  7436.  
  7437.                 EXECUTE @retcode = dbo.sp_remoteoption @publisher, 'distributor_admin',
  7438.                     'distributor_admin', trusted, 'false'
  7439.                 IF @@error <> 0 OR @retcode <> 0
  7440.                 BEGIN
  7441.                     RAISERROR (14075, 16, -1)
  7442.                     RETURN (1)
  7443.                 END
  7444.             END
  7445.  
  7446.             /*
  7447.             ** Set the trusted property
  7448.             */
  7449.             UPDATE msdb..MSdistpublishers SET trusted = @new_trusted
  7450.                 WHERE UPPER(name) = UPPER(@publisher) collate database_default
  7451.             IF @@error <> 0
  7452.                 BEGIN
  7453.                     RETURN (1)
  7454.                 END
  7455.         END
  7456.  
  7457.   
  7458.     /*
  7459.     ** Return succeed.
  7460.     */
  7461.     RAISERROR (21035, 10, -1, @property)
  7462.  
  7463. DONE:    
  7464.     RETURN (0)
  7465. go
  7466.  
  7467. --------------------------------------------------------------------------------
  7468. --. sp_MScopyscriptfile
  7469. --------------------------------------------------------------------------------
  7470. if exists (select * from sysobjects
  7471.     where type = 'P' and name = 'sp_MScopyscriptfile')
  7472. drop procedure sp_MScopyscriptfile
  7473. go
  7474. create proc sp_MScopyscriptfile (
  7475.     @scriptfile nvarchar(4000), 
  7476.     @cmd nvarchar(4000) OUTPUT
  7477. )
  7478. as
  7479. declare @directory nvarchar(4000)
  7480. declare @filename nvarchar(1024)
  7481. declare @subdirectory nvarchar(1024)
  7482. declare @retcode int
  7483.  
  7484. IF @scriptfile IS NULL
  7485. BEGIN
  7486.     RAISERROR (14043, 16, -1, '@scriptfile')
  7487.     RETURN (1)
  7488. END
  7489. -- Create the directory on distributor to store script.
  7490. exec sp_helpdistributor @directory=@directory OUTPUT
  7491. select @subdirectory = convert(nvarchar(64), GetDate(), 121)
  7492. select @subdirectory = replace(@subdirectory, N'-', N'')
  7493. select @subdirectory = replace(@subdirectory, N' ', N'')
  7494. select @subdirectory = replace(@subdirectory, N':', N'')
  7495. select @subdirectory = replace(@subdirectory, N'.', N'')
  7496. if(right(@directory, 1) = N'\')
  7497.     select @directory = @directory + @subdirectory
  7498. else
  7499.     select @directory = @directory + N'\' + @subdirectory
  7500. select @cmd = N'md "' + fn_escapecmdshellsymbolsremovequotes(@directory) collate database_default + '"'
  7501. exec @retcode = master..xp_cmdshell @cmd, NO_OUTPUT
  7502. if(@retcode <> 0)
  7503. begin
  7504.     raiserror(21330, 16, -1, @cmd)
  7505.     return (1)
  7506. end
  7507.  
  7508. -- Copy script to distributor
  7509. select @cmd = N'copy "' + fn_escapecmdshellsymbolsremovequotes(@scriptfile) collate database_default + N'" "' + fn_escapecmdshellsymbolsremovequotes(@directory) collate database_default + N'"'
  7510. exec @retcode = master..xp_cmdshell @cmd, NO_OUTPUT
  7511. if(@retcode <> 0)
  7512. begin 
  7513.     raiserror(21331, 16, -1, @cmd)
  7514.     return (1)
  7515. end
  7516.  
  7517. -- Prepare command, to be posted to log
  7518. select @filename = right(@scriptfile, charindex(N'\', reverse(@scriptfile)))
  7519. if(left(@filename, 1) = N'\')    
  7520.     select @cmd = @directory + @filename
  7521. else
  7522.     select @cmd = @directory + N'\' + @filename
  7523. go
  7524. exec sp_MS_marksystemobject sp_MScopyscriptfile
  7525. go
  7526.  
  7527. --------------------------------------------------------------------------------
  7528. --. sp_replproberemoteserver
  7529. --------------------------------------------------------------------------------
  7530. if exists (select * from sysobjects
  7531.     where type = 'P' and name = 'sp_replproberemoteserver')
  7532. drop procedure sp_replproberemoteserver
  7533. go
  7534. raiserror('Creating procedure sp_replproberemoteserver', 0,1)
  7535. go
  7536. --
  7537. -- Name: sp_replproberemoteserver
  7538. --
  7539. -- Description: This is a lightweight wrapper for calling xp_replproberremsrv
  7540. --              with the added nicety of looking up the agent command line
  7541. --              using the given jobid. This procedure supports two different
  7542. --              modes of operation based on the @no_rpc parameter. If the 
  7543. --              @no_rpc parameter is 1, this procedure will not attempt to make
  7544. --              rpc call to the Distributor. The local mode is mainly useful 
  7545. --              for verifying remote pull subscription agent.
  7546. -- 
  7547. -- Parameters: @remoteservername sysname (mandatory) 
  7548. --             @agent_type nvarchar(16) (optional, default = null) 
  7549. --             @agent_jobid uniqueidentifier (optional default = null)
  7550. --             @no_rpc bit (optional default = 0)
  7551. --
  7552. -- Notes: If @job_id is null, only activation verification will be carried
  7553. --        out.
  7554. --
  7555. -- Security: Execute permission of this procedure is granted to public. 
  7556. --           Internal security check is performed inside this procedure to
  7557. --           make sure that the caller is at least a db_owner of the current 
  7558. --           database.
  7559. --
  7560. -- Result: 'probe_succeeded' 0 or 1
  7561. --
  7562. -- Returns: 0    - succeeded
  7563. --          <> 0 - failed
  7564. --
  7565. create procedure dbo.sp_replproberemoteserver (
  7566.     @remoteservername sysname,
  7567.     @agent_type       nvarchar(16) = null,
  7568.     @agent_jobid      uniqueidentifier = null,
  7569.     @no_rpc           bit = 0
  7570.     ) 
  7571. as
  7572. begin
  7573.     set nocount on
  7574.     declare @retcode        int
  7575.     declare @commandline    nvarchar(3200)
  7576.     declare @distributor    sysname
  7577.     declare @distributiondb sysname     
  7578.     declare @distproc       nvarchar(255)
  7579.     declare @succeeded      nvarchar(10)
  7580.  
  7581.     select @retcode = 0
  7582.     select @commandline = null
  7583.     select @succeeded = null
  7584.  
  7585.     -- security check, db_owner
  7586.     -- Note that this proc can be called from either a publisher database or
  7587.     -- a subscriber database
  7588.     exec @retcode = dbo.sp_MSreplcheck_publish
  7589.     if @@error <> 0 or @retcode <> 0
  7590.         return (1)
  7591.     
  7592.     if @agent_type is null
  7593.     begin
  7594.         select @agent_type = 'distribution'
  7595.     end
  7596.     
  7597.     -- @remoteservername cannot be null or empty
  7598.     select @remoteservername = rtrim(ltrim(@remoteservername))
  7599.     if @remoteservername is null or
  7600.        @remoteservername = N''
  7601.     begin
  7602.         raiserror(21263,16,-1,'@remoteservername')
  7603.         return 1
  7604.     end     
  7605.     
  7606.     -- @agent_type must be 'distribution' or 'merge'
  7607.     if @agent_type not in (N'distribution', N'merge')
  7608.     begin
  7609.         raiserror(21182,16,-1) 
  7610.         return 1
  7611.     end
  7612.  
  7613.     -- Get Distributor information
  7614.     if @no_rpc = 0
  7615.     begin
  7616.         exec @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor output,
  7617.                                           @distribdb = @distributiondb output
  7618.         if @@error <> 0 or @retcode <> 0
  7619.             return 1
  7620.     end
  7621.     else
  7622.     begin
  7623.         select @distributor = @@servername
  7624.     end
  7625.  
  7626.     if upper(@@servername) <> upper(@distributor)
  7627.     begin
  7628.         select @distproc = ltrim(rtrim(@distributor)) + '.' + 
  7629.             'master.dbo.sp_replproberemoteserver'
  7630.         exec @retcode = @distproc @remoteservername, 
  7631.                                   @agent_type, 
  7632.                                   @agent_jobid, 
  7633.                                   1
  7634.         return @retcode
  7635.     end        
  7636.     else
  7637.     begin
  7638.         -- If the given @job_id is not null, try to get
  7639.         -- the agent command line
  7640.         if @agent_jobid is not null 
  7641.         begin
  7642.             select @commandline = fn_replgetagentcommandlinefromjobid(
  7643.                 @agent_type,
  7644.                 @agent_jobid) collate database_default
  7645.  
  7646.             if @commandline is null
  7647.             begin
  7648.                 raiserror(21361,6,-1, @agent_type) 
  7649.                 select 'probe_succeeded' = 0
  7650.                 return 1
  7651.             end
  7652.  
  7653.         end 
  7654.  
  7655.         exec @retcode = master.dbo.xp_replproberemsrv 
  7656.             @remoteservername, 
  7657.             @agent_type, 
  7658.             @succeeded output,
  7659.             @commandline 
  7660.  
  7661.         if lower(@succeeded collate SQL_Latin1_General_CP1_CS_AS) = N'true'  
  7662.             select 'probe_succeeded' = 1
  7663.         else
  7664.             select 'probe_succeeded' = 0
  7665.  
  7666.         return @retcode
  7667.     end
  7668.  
  7669.     select 'probe_succeeded' = 0
  7670.  
  7671.     return 1
  7672. end
  7673. go
  7674. exec sp_MS_marksystemobject sp_replproberemoteserver
  7675. go
  7676. grant execute on dbo.sp_replproberemoteserver to public
  7677. go
  7678. if exists (select * from sysobjects
  7679.      where type = 'X'
  7680.           and name = 'sp_replsetoriginator_internal' )
  7681. exec dbo.sp_dropextendedproc 'sp_replsetoriginator_internal'
  7682. go
  7683. sp_addextendedproc  'sp_replsetoriginator_internal', 'replsetoriginator extended procedure'
  7684. go
  7685. if exists (select * from sysobjects
  7686.      where type = 'X'
  7687.           and name = 'sp_replsetoriginator' )
  7688. exec dbo.sp_dropextendedproc 'sp_replsetoriginator'
  7689. go
  7690. if exists (select * from sysobjects
  7691.      where type = 'P'
  7692.           and name = 'sp_replsetoriginator' )
  7693. drop procedure sp_replsetoriginator
  7694. go
  7695. --
  7696. -- Name:    
  7697. --          sp_replsetoriginator
  7698. --          
  7699. -- Description: 
  7700. --          wrapper for sp_replsetoriginator_internal with DBO check
  7701. --  
  7702. -- Security: 
  7703. --          DBO only
  7704. --
  7705. -- Returns:      0 : success
  7706. --        1 : failure          
  7707. --      
  7708. -- Owner:   
  7709. --          qunguo
  7710. --
  7711. --
  7712. raiserror('Creating procedure sp_replsetoriginator',0,1)
  7713. go
  7714. create proc sp_replsetoriginator (
  7715.     @originator_srv sysname, 
  7716.     @originator_db sysname
  7717. )
  7718. as
  7719.     declare @retcode int
  7720.     /*
  7721.         ** Security Check, this proc is only called by distrib.exe, against sub db as DBO
  7722.         */
  7723.         exec @retcode = dbo.sp_MSreplcheck_subscribe
  7724.         if @@ERROR <> 0 or @retcode <> 0
  7725.     begin
  7726.             return(1)
  7727.     end
  7728.  
  7729.         exec @retcode = dbo.sp_replsetoriginator_internal @originator_srv, @originator_db
  7730.         if @@ERROR <> 0 or @retcode <> 0
  7731.     begin
  7732.             return(1)
  7733.     end
  7734.  
  7735.     return 0
  7736. go
  7737. exec sp_MS_marksystemobject sp_replsetoriginator
  7738. go
  7739. grant execute on dbo.sp_replsetoriginator to public
  7740. go
  7741.  
  7742. if exists (select * from sysobjects
  7743.      where type = 'P'
  7744.           and name = 'sp_replsetoriginator_pal' )
  7745. drop procedure sp_replsetoriginator_pal
  7746. go
  7747. --
  7748. -- Name:    
  7749. --          sp_replsetoriginator_pal
  7750. --          
  7751. -- Description: 
  7752. --          wrapper for sp_replsetoriginator_internal with pull access check
  7753. --  
  7754. -- Security: 
  7755. --          DBO or PAL access
  7756. --
  7757. -- Returns:      0 : success
  7758. --        1 : failure          
  7759. --      
  7760. -- Owner:   
  7761. --          qunguo
  7762. --
  7763. --
  7764. raiserror('Creating procedure sp_replsetoriginator_pal',0,1)
  7765. go
  7766. create proc sp_replsetoriginator_pal (
  7767.     @originator_srv sysname, 
  7768.     @originator_db sysname,
  7769.     @publication sysname
  7770. )
  7771. as
  7772.     declare @retcode int
  7773.     /*
  7774.         ** Security Check, this is called by updatable subscriber in sync-tran proc, hence PAL access
  7775.         */
  7776.     exec @retcode = dbo.sp_MSreplcheck_pull @publication = @publication
  7777.     if @@error <> 0 or @retcode <> 0
  7778.     begin
  7779.         return (1)
  7780.     end
  7781.  
  7782.         exec @retcode = dbo.sp_replsetoriginator_internal @originator_srv, @originator_db
  7783.         if @@ERROR <> 0 or @retcode <> 0
  7784.     begin
  7785.             return(1)
  7786.     end
  7787.  
  7788.     return 0
  7789. go
  7790. exec sp_MS_marksystemobject sp_replsetoriginator_pal
  7791. go
  7792. grant execute on dbo.sp_replsetoriginator_pal to public
  7793. go
  7794. if exists (select * from sysobjects
  7795.          where type = 'X'
  7796.             and name = 'sp_replincrementlsn' )
  7797.     exec dbo.sp_dropextendedproc 'sp_replincrementlsn'
  7798. go
  7799. if exists (select * from sysobjects
  7800.          where type = 'P'
  7801.             and name = 'sp_replincrementlsn' )
  7802.     drop procedure sp_replincrementlsn
  7803.  
  7804. if exists (select * from sysobjects
  7805.          where type = 'X'
  7806.             and name = 'sp_replincrementlsn_internal' )
  7807.     exec dbo.sp_dropextendedproc 'sp_replincrementlsn_internal'
  7808. go
  7809. sp_addextendedproc  'sp_replincrementlsn_internal', 'replincrementlsn_internal extended procedure'
  7810. go
  7811. --
  7812. -- Name:    
  7813. --          sp_replincrementlsn
  7814. --          
  7815. -- Description: 
  7816. --          wrapper for sp_replincrementlsn_internal with DBO check
  7817. --  
  7818. -- Security: 
  7819. --          DBO only
  7820. --
  7821. -- Returns:      0 : success
  7822. --        1 : failure          
  7823. --      
  7824. -- Owner:   
  7825. --          qunguo
  7826. --
  7827. --
  7828. raiserror('Creating procedure sp_replincrementlsn',0,1)
  7829. go
  7830. create proc sp_replincrementlsn (
  7831.     @xact_seqno binary(10) OUTPUT
  7832. )
  7833. as
  7834.     declare @retcode int
  7835.     /*
  7836.         ** Security Check, this proc is called by snapshot agent or sp_repladd(drop)column, against pub db as DBO
  7837.         */
  7838.         exec @retcode = dbo.sp_MSreplcheck_publish
  7839.         if @@ERROR <> 0 or @retcode <> 0
  7840.     begin
  7841.             return(1)
  7842.     end
  7843.  
  7844.         exec @retcode = dbo.sp_replincrementlsn_internal @xact_seqno OUTPUT
  7845.         if @@ERROR <> 0 or @retcode <> 0
  7846.     begin
  7847.             return(1)
  7848.     end
  7849.  
  7850.     return 0
  7851. go
  7852. exec sp_MS_marksystemobject sp_replincrementlsn
  7853. go
  7854. grant execute on dbo.sp_replincrementlsn to public
  7855. go
  7856.  
  7857. if exists (select * from sysobjects
  7858.     where type = 'X'
  7859.                 and name = 'sp_replpostsyncstatus' )
  7860.         exec dbo.sp_dropextendedproc 'sp_replpostsyncstatus'
  7861.  
  7862. if exists (select * from sysobjects
  7863.     where type = 'P'
  7864.                  and name = 'sp_replpostsyncstatus' )
  7865.         drop procedure sp_replpostsyncstatus
  7866.  
  7867. if exists (select * from sysobjects
  7868.         where type = 'X'
  7869.                  and name = 'sp_replpostsyncstatus_int' )
  7870.         exec dbo.sp_dropextendedproc 'sp_replpostsyncstatus_int'
  7871. go
  7872. sp_addextendedproc  'sp_replpostsyncstatus_int', 'sp_replpostsyncstatus_int extended procedure'
  7873. go
  7874.  
  7875. --
  7876. -- Name:    
  7877. --          sp_replpostsyncstatus
  7878. --          
  7879. -- Description: 
  7880. --          wrapper for sp_replpostsyncstatus_int with DBO check
  7881. --  
  7882. -- Security: 
  7883. --          DBO only
  7884. --
  7885. -- Returns:      0 : success
  7886. --        1 : failure          
  7887. --      
  7888. -- Owner:   
  7889. --          qunguo
  7890. --
  7891. --
  7892. raiserror('Creating procedure sp_replpostsyncstatus',0,1)
  7893. go
  7894. create proc sp_replpostsyncstatus (
  7895.     @pubid int, 
  7896.     @artid int, 
  7897.     @syncstat int, 
  7898.     @xact_seqno binary(10) OUTPUT
  7899. )
  7900. as
  7901.     declare @retcode int
  7902.     /*
  7903.         ** Security Check, this proc is called by snapshot agent as DBO on publisher
  7904.         */
  7905.         exec @retcode = dbo.sp_MSreplcheck_publish
  7906.         if @@ERROR <> 0 or @retcode <> 0
  7907.     begin
  7908.             return(1)
  7909.     end
  7910.  
  7911.         exec @retcode = dbo.sp_replpostsyncstatus_int @pubid, @artid, @syncstat, @xact_seqno OUTPUT
  7912.         if @@ERROR <> 0 or @retcode <> 0
  7913.     begin
  7914.             return(1)
  7915.     end
  7916.  
  7917.     return 0
  7918. go
  7919. exec sp_MS_marksystemobject sp_replpostsyncstatus
  7920. go
  7921. grant execute on dbo.sp_replpostsyncstatus to public
  7922. go
  7923.  
  7924.  
  7925. --------------------------------------------------------------------------------
  7926. --.    System objects (repltran.sql)
  7927. --------------------------------------------------------------------------------
  7928. if exists (select * from sysobjects
  7929.     where type = 'P' and name = 'sp_MScreate_pub_tables')
  7930. drop procedure sp_MScreate_pub_tables
  7931.  
  7932. print ''
  7933. print 'Creating procedure sp_MScreate_pub_tables'
  7934. go
  7935. CREATE PROCEDURE sp_MScreate_pub_tables
  7936. AS
  7937.     DECLARE @fError int
  7938.     SELECT @fError = 0
  7939.  
  7940.     -- enable 'create tables as pseudo system tables
  7941.  
  7942.     -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead
  7943.     -- exec dbo.sp_MS_upd_sysobj_category 1
  7944.  
  7945.  
  7946.     /* 
  7947.     ** Msg 226, Level 16, State 9
  7948.     ** CREATE TABLE system-table command not allowed within multi-statement transaction.
  7949.     */
  7950.     /*
  7951.     BEGIN TRAN sp_create_central_pub_tables
  7952.     */
  7953.     
  7954.     /* Creating 'sysarticles' */
  7955.     IF not exists (select * from sysobjects where name = 'sysarticles')
  7956.     BEGIN
  7957.         create table dbo.sysarticles
  7958.         (
  7959.         artid               int                 identity NOT NULL,
  7960.         columns             varbinary(32)       NULL,
  7961.         creation_script     nvarchar(255)       NULL,
  7962.         del_cmd             nvarchar(255)       NULL,
  7963.         description         nvarchar(255)       NULL,
  7964.         dest_table          sysname             NOT NULL,
  7965.         filter              int                 NOT NULL,
  7966.         filter_clause       ntext               NULL,
  7967.         ins_cmd             nvarchar(255)       NULL,
  7968.         name                sysname             NOT NULL,
  7969.         objid               int                 NOT NULL,
  7970.         pubid               int                 NOT NULL,
  7971.         pre_creation_cmd    tinyint             NOT NULL,
  7972.         status              tinyint             NOT NULL,
  7973.         sync_objid          int                 NOT NULL,
  7974.         type                tinyint             NOT NULL,
  7975.         upd_cmd             nvarchar(255)       NULL,
  7976.         schema_option       binary(8)           NULL,
  7977.         dest_owner          sysname             NULL
  7978.         -- Note: Please update sysextendedarticlesview whenever
  7979.         -- there is a schema change in sysarticles
  7980.         )
  7981.  
  7982.         EXEC dbo.sp_MS_marksystemobject 'sysarticles'
  7983.  
  7984.         IF @@error<>0
  7985.         BEGIN
  7986.             GOTO ERROR
  7987.         END
  7988.  
  7989.         create unique nonclustered index unc1sysarticles
  7990.             on sysarticles(artid, pubid) 
  7991.         
  7992.         IF @@error<>0
  7993.         BEGIN
  7994.             GOTO ERROR
  7995.         END
  7996.  
  7997.     END
  7998.  
  7999.     /* Creating 'sysschemaarticles' */
  8000.     IF not exists (select * from sysobjects where name = 'sysschemaarticles')
  8001.     BEGIN
  8002.         create table dbo.sysschemaarticles
  8003.         (
  8004.         artid               int                 NOT NULL,
  8005.         creation_script     nvarchar(255)       NULL,
  8006.         description         nvarchar(255)       NULL,
  8007.         dest_object         sysname             NOT NULL,
  8008.         name                sysname             NOT NULL,
  8009.         objid               int                 NOT NULL,
  8010.         pubid               int                 NOT NULL,
  8011.         pre_creation_cmd    tinyint             NOT NULL,
  8012.         status              int                 NOT NULL,
  8013.         type                tinyint             NOT NULL,
  8014.         schema_option       binary(8)           NULL,
  8015.         dest_owner          sysname             NULL
  8016.         )
  8017.         
  8018.         IF @@error<>0
  8019.         BEGIN
  8020.             GOTO ERROR
  8021.         END
  8022.  
  8023.         EXEC dbo.sp_MS_marksystemobject 'sysschemaarticles'
  8024.  
  8025.         IF @@error<>0
  8026.         BEGIN
  8027.             GOTO ERROR
  8028.         END
  8029.  
  8030.         create unique nonclustered index unc1sysschemaarticles
  8031.             on sysschemaarticles(artid, pubid)
  8032.  
  8033.         IF @@error<>0
  8034.         BEGIN
  8035.             GOTO ERROR
  8036.         END
  8037.         
  8038.     END
  8039.  
  8040.     /* Creating 'sysextendedarticlesview' */
  8041.     IF not exists (select * from sysobjects where name = 'sysextendedarticlesview')
  8042.     BEGIN
  8043.         exec ('create view dbo.sysextendedarticlesview
  8044.                as
  8045.                select * from sysarticles
  8046.                union all
  8047.                select artid, NULL, creation_script, NULL, description,
  8048.                dest_object, NULL, NULL, NULL, name, objid, pubid, 
  8049.                pre_creation_cmd, status, NULL, type, NULL, 
  8050.                schema_option, dest_owner from sysschemaarticles
  8051.                go')
  8052.  
  8053.         IF @@error<>0
  8054.         BEGIN
  8055.             GOTO ERROR
  8056.         END 
  8057.  
  8058.         EXEC dbo.sp_MS_marksystemobject 'sysextendedarticlesview'
  8059.  
  8060.         IF @@error<>0
  8061.         BEGIN
  8062.             GOTO ERROR
  8063.         END
  8064.  
  8065.     END
  8066.  
  8067.     /* Creating 'syspublications' */
  8068.     IF NOT EXISTS (select * from sysobjects where name = 'syspublications')
  8069.     BEGIN
  8070.         CREATE TABLE dbo.syspublications (
  8071.         description                 nvarchar(255)   NULL,
  8072.         name                        sysname         NOT NULL,
  8073.         pubid                       int    identity NOT NULL,
  8074.         repl_freq                   tinyint         NOT NULL,
  8075.         status                      tinyint         NOT NULL,
  8076.         sync_method                 tinyint         NOT NULL,
  8077.         snapshot_jobid              binary(16)        NULL,
  8078.         independent_agent           bit             NOT NULL,
  8079.         immediate_sync              bit             NOT NULL,
  8080.         enabled_for_internet        bit             NOT NULL,
  8081.         allow_push                  bit             NOT NULL,
  8082.         allow_pull                  bit             NOT NULL,
  8083.         allow_anonymous             bit             NOT NULL,
  8084.         immediate_sync_ready        bit             NOT NULL,
  8085.         -- SyncTran
  8086.         allow_sync_tran             bit             NOT NULL,
  8087.         autogen_sync_procs          bit             NOT NULL,
  8088.         retention                   int             NULL,
  8089.         -- The following are post 7.0
  8090.         allow_queued_tran           bit   default 0    not null, 
  8091.         -- portable snapshot support
  8092.         snapshot_in_defaultfolder           bit   default 1 NOT NULL,         
  8093.         alt_snapshot_folder         nvarchar(255)   NULL,
  8094.         -- snapshot pre/post- command
  8095.         pre_snapshot_script         nvarchar(255)   NULL,
  8096.         post_snapshot_script        nvarchar(255)   NULL,
  8097.         -- Snapshot compression
  8098.         compress_snapshot           bit   default 0 NOT NULL,          
  8099.         -- Post 7.0 Ftp support
  8100.         ftp_address                 sysname         NULL,
  8101.         ftp_port                    int   default 21 NOT NULL,
  8102.         ftp_subdirectory            nvarchar(255)   NULL,
  8103.         ftp_login                   sysname         NULL default N'anonymous',
  8104.         ftp_password                nvarchar(524)   NULL,
  8105.         allow_dts        bit default 0 not null,
  8106.         allow_subscription_copy        bit default 0 not null,
  8107.         centralized_conflicts        bit                NULL, -- 0 False, 1 True
  8108.         conflict_retention            int                NULL, -- 60
  8109.         conflict_policy                int             NULL, -- 1 = PubWins, 2 = SubWins, 3 = Reinit
  8110.         queue_type                    int                NULL,  -- 1 = MSMQ, 2 = SQL
  8111.         ad_guidname                    sysname            NULL,
  8112.         backward_comp_level    int default 10 not NULL -- default is sphinx
  8113.         )
  8114.  
  8115.         EXEC dbo.sp_MS_marksystemobject 'syspublications'
  8116.  
  8117.         IF @@ERROR <> 0
  8118.         BEGIN
  8119.             GOTO ERROR
  8120.         END
  8121.  
  8122.         create unique clustered index uc1syspublications
  8123.             on syspublications (pubid) 
  8124.         IF @@ERROR <> 0
  8125.         BEGIN
  8126.             GOTO ERROR
  8127.         END
  8128.  
  8129.         create unique nonclustered index unc2syspublications
  8130.             on syspublications (name)
  8131.  
  8132.         IF @@ERROR <> 0
  8133.         BEGIN
  8134.             GOTO ERROR
  8135.         END
  8136.  
  8137.     END
  8138.  
  8139.        /* Creating 'syssubscriptions' */
  8140.     IF not exists (select * from sysobjects where name = 'syssubscriptions')
  8141.     BEGIN
  8142.  
  8143.         CREATE TABLE dbo.syssubscriptions
  8144.         (
  8145.         artid                    int                NOT NULL,
  8146.         srvid                    smallint        NOT NULL,
  8147.         dest_db                    sysname        NOT NULL,
  8148.         status                    tinyint            NOT NULL,
  8149.         sync_type                tinyint            NOT NULL,
  8150.         login_name                sysname        NOT NULL,
  8151.         subscription_type        int                NOT NULL,
  8152.         distribution_jobid      binary(16)          NULL,
  8153.         timestamp NOT NULL,
  8154.         -- SyncTran
  8155.         update_mode             tinyint            NOT NULL, -- 0 (read only), 1 (Sync Tran), 
  8156.                                                              -- Queued Tran
  8157.                                                              -- 2 (Queued Tran) , 3 (Failover), 4(sqlqueued), 5(sqlqueued failover)
  8158.         loopback_detection      bit NOT NULL,
  8159.           queued_reinit           bit DEFAULT 0 NOT NULL 
  8160.       )
  8161.  
  8162.         EXEC dbo.sp_MS_marksystemobject 'syssubscriptions'
  8163.  
  8164.         IF @@ERROR <> 0
  8165.         BEGIN
  8166.             GOTO ERROR
  8167.         END
  8168.  
  8169.         create unique nonclustered index unc1syssubscriptions
  8170.             on syssubscriptions (artid, srvid, dest_db)
  8171.  
  8172.         IF @@ERROR <> 0
  8173.         BEGIN
  8174.             GOTO ERROR
  8175.         END
  8176.  
  8177.     END
  8178.  
  8179.     -- SyncTran
  8180.     /* Creating 'sysarticleupdates' */
  8181.  
  8182.     IF not exists (select * from sysobjects where name = 'sysarticleupdates')
  8183.     BEGIN
  8184.  
  8185.         CREATE TABLE dbo.sysarticleupdates
  8186.         (
  8187.         artid                  int       NOT NULL,
  8188.         pubid                  int       NOT NULL,
  8189.         sync_ins_proc          int       NOT NULL,     -- ID of sproc handling Insert Sync Transactions
  8190.         sync_upd_proc          int       NOT NULL,     -- ID of sproc handling Update Sync Transactions
  8191.         sync_del_proc          int       NOT NULL,     -- ID of sproc handling Delete Sync Transactions
  8192.         autogen                bit       NOT NULL,
  8193.         sync_upd_trig          int       NOT NULL,     -- Note 7.0 upgrade issue
  8194.         conflict_tableid       int         NULL,           -- ID of conflict table for this article
  8195.         ins_conflict_proc       int         NULL,           -- ID of sproc to log conflicts
  8196.         identity_support       bit default 0 not null  -- Whether or not do auto identity range 
  8197.         )     
  8198.  
  8199.         IF @@ERROR <> 0
  8200.         BEGIN
  8201.             GOTO ERROR
  8202.         END
  8203.  
  8204.  
  8205.         -- mark the index as a system object
  8206.         exec dbo.sp_MS_marksystemobject 'sysarticleupdates'
  8207.  
  8208.         IF @@ERROR <> 0
  8209.         BEGIN
  8210.             GOTO ERROR
  8211.         END
  8212.  
  8213.         create unique nonclustered index unc1sysarticleupdates
  8214.             on sysarticleupdates (artid, pubid)
  8215.  
  8216.         IF @@ERROR <> 0
  8217.         BEGIN
  8218.             GOTO ERROR
  8219.         END
  8220.     END
  8221.     -- end SyncTran
  8222.  
  8223.  
  8224.     IF not exists (select * from sysobjects where name = 'MSpub_identity_range')
  8225.     BEGIN
  8226.         CREATE TABLE dbo.MSpub_identity_range
  8227.         (
  8228.             objid int not null,
  8229.             range bigint not null,
  8230.             pub_range bigint not null,
  8231.             current_pub_range bigint not null,
  8232.             threshold int not null,
  8233.             last_seed bigint null -- It will be not when uninitialized.
  8234.         )     
  8235.  
  8236.         IF @@ERROR <> 0
  8237.         BEGIN
  8238.             GOTO ERROR
  8239.         END
  8240.  
  8241.  
  8242.         -- mark the index as a system object
  8243.         exec dbo.sp_MS_marksystemobject 'MSpub_identity_range'
  8244.  
  8245.         IF @@ERROR <> 0
  8246.         BEGIN
  8247.             GOTO ERROR
  8248.         END
  8249.  
  8250.         create unique nonclustered index unc1MSpub_identity_range
  8251.             on MSpub_identity_range (objid)
  8252.  
  8253.         IF @@ERROR <> 0
  8254.         BEGIN
  8255.             GOTO ERROR
  8256.         END
  8257.     END
  8258.  
  8259.     IF not exists (select * from sysobjects where name = 'systranschemas' and uid = 1)
  8260.     BEGIN
  8261.         CREATE TABLE dbo.systranschemas
  8262.         (
  8263.             tabid int not null,
  8264.             startlsn binary(10) not null,
  8265.             endlsn binary(10) not null
  8266.     )     
  8267.  
  8268.         IF @@ERROR <> 0
  8269.         BEGIN
  8270.             GOTO ERROR
  8271.         END
  8272.  
  8273.         -- mark the index as a system object
  8274.         exec dbo.sp_MS_marksystemobject 'systranschemas'
  8275.  
  8276.         IF @@ERROR <> 0
  8277.         BEGIN
  8278.             GOTO ERROR
  8279.         END
  8280.  
  8281.         create unique clustered index uncsystranschemas
  8282.             on systranschemas (startlsn)
  8283.  
  8284.         IF @@ERROR <> 0
  8285.         BEGIN
  8286.             GOTO ERROR
  8287.         END
  8288.     END
  8289.  
  8290. CLEANUP:
  8291.  
  8292.     -- disable 'create tables as pseudo system tables
  8293.     -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead
  8294.     -- exec dbo.sp_MS_upd_sysobj_category 2
  8295.     RETURN( @fError )
  8296.  
  8297. ERROR:
  8298.  
  8299.     select @fError = 1
  8300.     GOTO CLEANUP
  8301.  
  8302. GO
  8303.  
  8304. EXEC dbo.sp_MS_marksystemobject sp_MScreate_pub_tables
  8305. GO
  8306. --------------------------------------------------------------------------------
  8307. --. sp_articlesynctranprocs
  8308. --------------------------------------------------------------------------------
  8309. if exists (select * from sysobjects
  8310.     where type = 'P' and name = 'sp_articlesynctranprocs')
  8311. revoke exec on dbo.sp_articlesynctranprocs from public
  8312.  
  8313. --------------------------------------------------------------------------------
  8314. --. sp_gettypestring
  8315. --------------------------------------------------------------------------------
  8316. if exists (select * from sysobjects
  8317.     where type = 'P' and name = 'sp_gettypestring')
  8318. revoke exec on dbo.sp_gettypestring from public
  8319.  
  8320. --------------------------------------------------------------------------------
  8321. --. sp_MSgettranconflictname
  8322. --------------------------------------------------------------------------------
  8323. if exists (select * from sysobjects
  8324.     where type = 'P' and name = 'sp_MSgettranconflictname')
  8325. revoke execute on dbo.sp_MSgettranconflictname from public
  8326.  
  8327. --------------------------------------------------------------------------------
  8328. --. sp_MSmakeconflicttable
  8329. --------------------------------------------------------------------------------
  8330. if exists (select * from sysobjects
  8331.     where type = 'P' and name = 'sp_MSmakeconflicttable')
  8332. revoke execute on dbo.sp_MSmakeconflicttable from public
  8333.  
  8334. --------------------------------------------------------------------------------
  8335. --. sp_MSmaketrancftproc
  8336. --------------------------------------------------------------------------------
  8337. if exists (select * from sysobjects
  8338.     where type = 'P' and name = 'sp_MSmaketrancftproc')
  8339. revoke execute on dbo.sp_MSmaketrancftproc from public
  8340.  
  8341. --------------------------------------------------------------------------------
  8342. --. sp_MSmark_proc_norepl
  8343. --------------------------------------------------------------------------------
  8344. if exists (select * from sysobjects
  8345.     where type = 'P' and name = 'sp_MSmark_proc_norepl')
  8346. revoke execute on dbo.sp_MSmark_proc_norepl from public
  8347.  
  8348. --------------------------------------------------------------------------------
  8349. --. sp_MSscript_beginproc
  8350. --------------------------------------------------------------------------------
  8351. if exists (select * from sysobjects
  8352.     where type = 'P' and name = 'sp_MSscript_beginproc')
  8353. revoke execute on dbo.sp_MSscript_beginproc  from public
  8354.  
  8355. --------------------------------------------------------------------------------
  8356. --. sp_MSscript_compensating_send
  8357. --------------------------------------------------------------------------------
  8358. if exists (select * from sysobjects
  8359.     where type = 'P' and name = 'sp_MSscript_compensating_send')
  8360. revoke execute on dbo.sp_MSscript_compensating_send from public
  8361.  
  8362. --------------------------------------------------------------------------------
  8363. --. sp_MSscript_delete_pubwins
  8364. --------------------------------------------------------------------------------
  8365. if exists (select * from sysobjects
  8366.     where type = 'P' and name = 'sp_MSscript_delete_pubwins')
  8367. revoke execute on dbo.sp_MSscript_delete_pubwins from public
  8368.  
  8369. --------------------------------------------------------------------------------
  8370. --. sp_MSscript_delete_statement
  8371. --------------------------------------------------------------------------------
  8372. if exists (select * from sysobjects
  8373.     where type = 'P' and name = 'sp_MSscript_delete_statement')
  8374. revoke execute on dbo.sp_MSscript_delete_statement from public
  8375.  
  8376. --------------------------------------------------------------------------------
  8377. --. sp_MSscript_delete_subwins
  8378. --------------------------------------------------------------------------------
  8379. if exists (select * from sysobjects
  8380.     where type = 'P' and name = 'sp_MSscript_delete_subwins')
  8381. revoke execute on dbo.sp_MSscript_delete_subwins from public
  8382.  
  8383. --------------------------------------------------------------------------------
  8384. --. sp_MSscript_ExecutionMode_stmt
  8385. --------------------------------------------------------------------------------
  8386. if exists (select * from sysobjects
  8387.     where type = 'P' and name = 'sp_MSscript_ExecutionMode_stmt')
  8388. revoke execute on dbo.sp_MSscript_ExecutionMode_stmt from public
  8389.  
  8390. --------------------------------------------------------------------------------
  8391. --. sp_MSscript_insert_statement
  8392. --------------------------------------------------------------------------------
  8393. if exists (select * from sysobjects
  8394.     where type = 'P' and name = 'sp_MSscript_insert_statement')
  8395. revoke execute on dbo.sp_MSscript_insert_statement from public
  8396.  
  8397. --------------------------------------------------------------------------------
  8398. --. sp_MSscript_security
  8399. --------------------------------------------------------------------------------
  8400. if exists (select * from sysobjects
  8401.     where type = 'P' and name = 'sp_MSscript_security')
  8402. revoke execute on dbo.sp_MSscript_security  from public
  8403.  
  8404. --------------------------------------------------------------------------------
  8405. --. sp_MSscript_update_statement
  8406. --------------------------------------------------------------------------------
  8407. if exists (select * from sysobjects
  8408.     where type = 'P' and name = 'sp_MSscript_update_statement')
  8409. revoke execute on dbo.sp_MSscript_update_statement from public
  8410.  
  8411. --------------------------------------------------------------------------------
  8412. --. sp_scriptpkwhereclause
  8413. --------------------------------------------------------------------------------
  8414. if exists (select * from sysobjects
  8415.     where type = 'P' and name = 'sp_scriptpkwhereclause')
  8416. revoke exec on dbo.sp_scriptpkwhereclause from public
  8417.  
  8418. --------------------------------------------------------------------------------
  8419. --. sp_scriptreconwhereclause
  8420. --------------------------------------------------------------------------------
  8421. if exists (select * from sysobjects
  8422.     where type = 'P' and name = 'sp_scriptreconwhereclause')
  8423. revoke exec on dbo.sp_scriptreconwhereclause from public
  8424.  
  8425. --------------------------------------------------------------------------------
  8426. --. sp_scriptupdateparams
  8427. --------------------------------------------------------------------------------
  8428. if exists (select * from sysobjects
  8429.     where type = 'P' and name = 'sp_scriptupdateparams')
  8430. revoke exec on dbo.sp_scriptupdateparams from public
  8431. go
  8432. --------------------------------------------------------------------------------
  8433. --. sp_MSscript_ExecutionMode_stmt
  8434. --------------------------------------------------------------------------------
  8435. if exists (select * from sysobjects
  8436.     where type = 'P' and name = 'sp_MSscript_ExecutionMode_stmt')
  8437. drop procedure sp_MSscript_ExecutionMode_stmt
  8438. go
  8439. raiserror('Creating procedure sp_MSscript_ExecutionMode_stmt', 0,1)
  8440. go
  8441. create procedure sp_MSscript_ExecutionMode_stmt (
  8442.     @publication sysname, 
  8443.     @article     sysname,
  8444.     @proctype    int = 0)        -- 0 insert, 1 delete, 2 update
  8445. as
  8446. begin
  8447.     declare @cmd        nvarchar(4000)
  8448.             ,@artid        int
  8449.             ,@pubid        int
  8450.             ,@queued_pub bit
  8451.  
  8452.     select @pubid = pubid, @queued_pub = allow_queued_tran 
  8453.         from syspublications where name = @publication
  8454.     select @artid = artid from sysarticles where name = @article and pubid = @pubid
  8455.  
  8456.     --
  8457.     -- For queued execution check if we are in the phase of reinitialization
  8458.     --
  8459.     select @cmd = N'
  8460.     ' + N'--
  8461.     ' + N'-- Check if we are in the process of Reinitialization
  8462.     ' + N'-- if yes then return
  8463.     ' + N'--' 
  8464.     insert into #proctext(procedure_text) values( @cmd )
  8465.  
  8466.     select @cmd = N'
  8467.     exec @retcode = dbo.sp_MSgetarticlereinitvalue @orig_server, @orig_db, ' + 
  8468.     cast(@artid as nvarchar(5)) + N', @reinit output
  8469.     if (@retcode != 0 or @@error != 0)
  8470.         return -1 '
  8471.     insert into #proctext(procedure_text) values( @cmd )
  8472.  
  8473.     select @cmd = N'
  8474.     if (@reinit = 1) -- Resync state
  8475.     begin
  8476.         if (@execution_mode = @immediate)
  8477.             return -2'
  8478.     if (@queued_pub = 1)
  8479.     begin
  8480.         select @cmd = @cmd + N'
  8481.         else
  8482.             return 4 -- Queued Resync state'
  8483.     end
  8484.     select @cmd = @cmd + N'
  8485.     end
  8486.     '
  8487.     insert into #proctext(procedure_text) values( @cmd )
  8488.     
  8489.     --
  8490.     -- set loopback detection for immediate
  8491.     --
  8492.     select @cmd = N'
  8493.     if (@execution_mode = @immediate)
  8494.     begin
  8495.         ' + N'--
  8496.         ' + N'-- For immediate
  8497.         ' + N'-- enable loopback detection
  8498.         ' + N'--
  8499.         exec @retcode = dbo.sp_replsetoriginator_pal @orig_server, @orig_db, ''' 
  8500.             + master.dbo.fn_MSgensqescstr(@publication) collate database_default + N'''
  8501.         if (@retcode != 0 or @@error != 0) 
  8502.             return -1
  8503.     end'
  8504.     insert into #proctext(procedure_text) values( @cmd )
  8505.  
  8506.     /********* no need to disable since we never enable
  8507.     if (@queued_pub = 1)
  8508.     begin
  8509.         --
  8510.         -- disable loopback for queued
  8511.         --
  8512.         select @cmd = N'
  8513.     else if (@execution_mode in (@QFirstPass, @QSubWins))
  8514.     begin
  8515.         ' + N'--
  8516.         ' + N'-- For queued
  8517.         ' + N'-- disable loopback detection
  8518.         ' + N'--
  8519.         exec @retcode = dbo.sp_replsetoriginator N''anull'', N''anull''
  8520.         if (@retcode != 0 or @@error != 0) 
  8521.             return -1
  8522.     end'
  8523.         insert into #proctext(procedure_text) values( @cmd )
  8524.     end
  8525.     **********/
  8526.  
  8527.     if (@queued_pub = 1)
  8528.     begin
  8529.         --
  8530.         -- Queued reinitialization mode execution
  8531.         --
  8532.         select @cmd = N'
  8533.     else if (@execution_mode = @QReinit)
  8534.     begin
  8535.         ' + N'--
  8536.         ' + N'-- For Queued reinitialization
  8537.         ' + N'-- Set the Queue and subscription for reinit
  8538.         ' + N'--'
  8539.         insert into #proctext(procedure_text) values( @cmd )
  8540.  
  8541.         select @cmd = N'
  8542.         exec @retcode = dbo.sp_reinitsubscription @publication = ''' 
  8543.             + master.dbo.fn_MSgensqescstr(@publication) collate database_default + N''', @article = ''' +  
  8544.             master.dbo.fn_MSgensqescstr(@article) collate database_default + N''', @subscriber = @orig_server, @destination_db = @orig_db
  8545.         if (@retcode != 0 or @@error != 0)
  8546.             return -1
  8547.         else
  8548.             return 0
  8549.     end'
  8550.  
  8551.         insert into #proctext(procedure_text) values( @cmd )
  8552.     end
  8553.  
  8554.     --
  8555.     -- all done
  8556.     --
  8557.     return 0
  8558. end 
  8559. go
  8560. EXEC dbo.sp_MS_marksystemobject sp_MSscript_ExecutionMode_stmt
  8561. GO
  8562.  
  8563. --------------------------------------------------------------------------------
  8564. --. sp_MSscript_pub_upd_trig
  8565. --------------------------------------------------------------------------------
  8566.  
  8567. if exists (select * from sysobjects
  8568.     where type = 'P' and name = 'sp_MSscript_pub_upd_trig')
  8569. drop procedure sp_MSscript_pub_upd_trig
  8570. go
  8571. raiserror('Creating procedure sp_MSscript_pub_upd_trig', 0,1)
  8572. go
  8573. create procedure sp_MSscript_pub_upd_trig
  8574. (
  8575.     @publication sysname, 
  8576.     @article     sysname,
  8577.     @procname    sysname
  8578. )
  8579. as
  8580. begin
  8581.     declare @cmd       nvarchar(4000)
  8582.     declare @qualname  nvarchar(512)
  8583.     declare @objid       int
  8584.     declare @columns   binary(32)
  8585.                 ,@retcode int
  8586.  
  8587.     set nocount on
  8588.     --
  8589.     -- security check
  8590.     --
  8591.     exec @retcode = dbo.sp_MSreplcheck_publish
  8592.     if @@error <> 0 or @retcode <> 0
  8593.     begin
  8594.         return (1)
  8595.     end
  8596.  
  8597.     -- Create temp table
  8598.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  8599.  
  8600.  
  8601.     -- Retrieve underlying table name and replicated columns
  8602.     select @objid = objid, @columns = columns from sysarticles a, syspublications p
  8603.         where a.name = @article and
  8604.               p.name = @publication and
  8605.               a.pubid = p.pubid
  8606.  
  8607.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  8608.  
  8609.     -- Trigger should be invoked for repl processes as well.
  8610.     select @cmd = N'create trigger ' + QUOTENAME(@procname) + N' on ' + @qualname + N' '
  8611.     select @cmd = @cmd + N'for update as ' 
  8612.  
  8613.     exec dbo.sp_MSflush_command @cmd output, 1
  8614.  
  8615.     insert into #proctext(procedure_text) values(N'
  8616. ')
  8617.     -- declare common local variables
  8618.     insert into #proctext(procedure_text) values 
  8619.         (N'declare @rc int
  8620. ')
  8621.     insert into #proctext(procedure_text) values(N'select @rc = @@ROWCOUNT 
  8622.  
  8623. ')
  8624.         
  8625.     -- Optimization. Return immediately if no row changed
  8626.     -- This must be at the beginning of the trigger to @@rowcount be overwritten.
  8627.     insert into #proctext(procedure_text) values(N'if @rc = 0 return 
  8628. ')
  8629.     insert into #proctext(procedure_text) values(N'if update (msrepl_tran_version) return 
  8630. ')
  8631.  
  8632.     -- update the version column of all the updated rows all at once.
  8633.     select @cmd = N'update ' + @qualname + N' set msrepl_tran_version = newid() from ' +
  8634.         @qualname + ', inserted '
  8635.     exec dbo.sp_MSflush_command @cmd output, 1
  8636.     insert into #proctext(procedure_text) values(N'
  8637. ')
  8638.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'version pk', null, 4
  8639.  
  8640.     insert into #proctext(procedure_text) values(N'
  8641. ')
  8642.     -- send fragments to client
  8643.     select procedure_text from #proctext order by c1 asc
  8644. end
  8645. go
  8646. EXEC dbo.sp_MS_marksystemobject sp_MSscript_pub_upd_trig
  8647. go
  8648. grant exec on dbo.sp_MSscript_pub_upd_trig to public
  8649. go
  8650.  
  8651. --------------------------------------------------------------------------------
  8652. --. sp_MSscript_sync_del_proc
  8653. --------------------------------------------------------------------------------
  8654.  
  8655. if exists (select * from sysobjects
  8656.     where type = 'P' and name = 'sp_MSscript_sync_del_proc')
  8657. drop procedure sp_MSscript_sync_del_proc
  8658. go
  8659. raiserror('Creating procedure sp_MSscript_sync_del_proc', 0,1)
  8660. go
  8661. create procedure sp_MSscript_sync_del_proc (
  8662.     @publication sysname, 
  8663.     @article     sysname,
  8664.     @procname    sysname)
  8665. as
  8666. BEGIN
  8667.     declare @source_objid int
  8668.     declare @colname sysname
  8669.     declare @indid int
  8670.     declare @cmd          nvarchar(4000)
  8671.     declare @columns      binary(32)
  8672.     declare @outvars      nvarchar(4000)
  8673.     declare @rc           int
  8674.     declare @error_cmd    tinyint
  8675.     declare @queued_pub bit
  8676.  
  8677.     set nocount on
  8678.     --
  8679.     -- security check
  8680.     --
  8681.     exec @rc = dbo.sp_MSreplcheck_publish
  8682.     if @@error <> 0 or @rc <> 0
  8683.     begin
  8684.         return (1)
  8685.     end
  8686.     --
  8687.     -- Create temp table
  8688.     --
  8689.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  8690.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  8691.  
  8692.     --
  8693.     -- proc definition
  8694.     --
  8695.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  8696.     if @rc = 0
  8697.         return
  8698.  
  8699.     --
  8700.     -- construct parameter list
  8701.     --
  8702.     exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null
  8703.  
  8704.     --
  8705.     -- add other parameters and start body of proc
  8706.     --
  8707.     exec dbo.sp_MSscript_procbodystart @queued_pub 
  8708.  
  8709.     --
  8710.     -- script out security check
  8711.     --
  8712.     exec dbo.sp_MSscript_security @publication
  8713.  
  8714.     --
  8715.     -- script the execution mode checks
  8716.     --
  8717.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 1
  8718.  
  8719.     --
  8720.     -- script out subscription validation
  8721.     --
  8722.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  8723.  
  8724.     --
  8725.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  8726.     -- *** Do we need to check this here - 
  8727.     -- *** we should be checking this when creating subscription
  8728.     -- 
  8729.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  8730.     if @rc = 1
  8731.         select @error_cmd = 1
  8732.     else
  8733.     begin
  8734.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  8735.         if (@outvars != null and @indid = 0)
  8736.             -- no insert/update allowed if timestamp/identity col and no unique index
  8737.             select @error_cmd = 1
  8738.         else
  8739.             select @error_cmd = 0        
  8740.     end
  8741.  
  8742.     if (@error_cmd = 0)
  8743.     begin
  8744.         -- Continue generation
  8745.         
  8746.         --
  8747.         -- script delete statemnt
  8748.         --
  8749.         exec dbo.sp_MSscript_delete_statement @publication, @article, @source_objid, @columns, @queued_pub
  8750.  
  8751.         --
  8752.         -- script queued specific stuff
  8753.         --
  8754.         if (@queued_pub = 1)
  8755.         begin
  8756.             --
  8757.             -- script Conflict resolution block for Subscriber Wins case
  8758.             --
  8759.             exec dbo.sp_MSscript_delete_subwins @publication, @article, @source_objid, @columns
  8760.  
  8761.             --
  8762.             -- script Conflict resolution block for Publisher Wins case
  8763.             --
  8764.             exec dbo.sp_MSscript_delete_pubwins @publication, @article, @source_objid, @columns
  8765.         end
  8766.         
  8767.         --
  8768.         -- script closing 
  8769.         --
  8770.         exec dbo.sp_MSscript_endproc @source_objid, 'del', @columns, @outvars, @queued_pub
  8771.     end
  8772.     else
  8773.     begin
  8774.         --
  8775.         -- Generate error command and finish
  8776.         --
  8777.         insert into #proctext(procedure_text) values( N'
  8778.     exec sp_MSreplraiserror 20516
  8779. END
  8780. ')
  8781.     end
  8782.                   
  8783.     --
  8784.     -- send fragments to client
  8785.     --
  8786.     select procedure_text from #proctext order by c1 asc
  8787.  
  8788. END
  8789. go
  8790. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_del_proc
  8791. GO
  8792. grant exec on dbo.sp_MSscript_sync_del_proc to public
  8793. go
  8794.  
  8795. --------------------------------------------------------------------------------
  8796. --. sp_MSscript_sync_ins_proc
  8797. --------------------------------------------------------------------------------
  8798.  
  8799. if exists (select * from sysobjects
  8800.     where type = 'P' and name = 'sp_MSscript_sync_ins_proc')
  8801. drop procedure sp_MSscript_sync_ins_proc
  8802. go
  8803. raiserror('Creating procedure sp_MSscript_sync_ins_proc', 0,1)
  8804. go
  8805. create procedure sp_MSscript_sync_ins_proc (
  8806.     @publication sysname, 
  8807.     @article     sysname,
  8808.     @procname    sysname)
  8809. as
  8810. BEGIN
  8811.     declare @source_objid int
  8812.             ,@colname sysname
  8813.             ,@indid int
  8814.             ,@cmd          nvarchar(4000)
  8815.             ,@columns      binary(32)
  8816.             ,@outvars      nvarchar(4000)
  8817.             ,@rc           int
  8818.             ,@error_cmd    tinyint
  8819.             ,@identity_insert bit
  8820.             ,@queued_pub bit
  8821.  
  8822.     set nocount on
  8823.     --
  8824.     -- security check
  8825.     --
  8826.     exec @rc = dbo.sp_MSreplcheck_publish
  8827.     if @@error <> 0 or @rc <> 0
  8828.     begin
  8829.         return (1)
  8830.     end
  8831.     --
  8832.     -- Create temp table
  8833.     --
  8834.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  8835.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  8836.  
  8837.     --
  8838.     -- proc definition
  8839.     --
  8840.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  8841.     if @rc = 0
  8842.         return
  8843.  
  8844.     --
  8845.     -- construct parameter list
  8846.     --
  8847.     exec dbo.sp_MSscript_params @source_objid, @columns, null, 1,  @outvars output
  8848.  
  8849.     --
  8850.     -- add other parameters and start body of proc
  8851.     --
  8852.     exec dbo.sp_MSscript_procbodystart @queued_pub
  8853.  
  8854.     --
  8855.     -- script out security check
  8856.     --
  8857.     exec dbo.sp_MSscript_security @publication
  8858.  
  8859.     --
  8860.     -- script the execution mode checks
  8861.     --
  8862.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 0
  8863.  
  8864.     --
  8865.     -- script out subscription validation
  8866.     --
  8867.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  8868.  
  8869.     --
  8870.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  8871.     -- *** Do we need to check this here - 
  8872.     -- *** we should be checking this when creating subscription
  8873.     -- 
  8874.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  8875.     if @rc = 1
  8876.         select @error_cmd = 1
  8877.     else
  8878.     begin
  8879.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  8880.         if (@outvars != null and @indid = 0)
  8881.             -- no insert/update allowed if timestamp/identity col and no unique index
  8882.             select @error_cmd = 1
  8883.         else
  8884.             select @error_cmd = 0        
  8885.     end
  8886.  
  8887.     if (@error_cmd = 0)
  8888.     begin
  8889.         -- Continue generation
  8890.     
  8891.         -- Check to see if identity insert must be turned on
  8892.         -- i.e. Does the table has identity that are included in the partition?
  8893.         exec sp_MSis_identity_insert @publication, @article, @identity_insert output
  8894.         --
  8895.         -- script insert statemnt
  8896.         --
  8897.         exec dbo.sp_MSscript_insert_statement @source_objid, @columns, @identity_insert, @queued_pub
  8898.  
  8899.         --
  8900.         -- script queued specific stuff
  8901.         --
  8902.         if (@queued_pub = 1)
  8903.         begin
  8904.             --
  8905.             -- script Conflict resolution block for Subscriber Wins case
  8906.             --
  8907.             exec dbo.sp_MSscript_insert_subwins @publication, @article, @source_objid, @columns, @identity_insert
  8908.  
  8909.             --
  8910.             -- script Conflict resolution block for Publisher Wins case
  8911.             --
  8912.             exec dbo.sp_MSscript_insert_pubwins @publication, @article, @source_objid, @columns
  8913.         end
  8914.         
  8915.         --
  8916.         -- script closing 
  8917.         --
  8918.         exec dbo.sp_MSscript_endproc @source_objid, 'ins', @columns, @outvars, @queued_pub
  8919.     end
  8920.     else
  8921.     begin
  8922.         --
  8923.         -- Generate error command and finish
  8924.         --
  8925.         insert into #proctext(procedure_text) values( N'
  8926.     exec sp_MSreplraiserror 20516
  8927. END
  8928. ')
  8929.     end
  8930.                   
  8931.     --
  8932.     -- send fragments to client
  8933.     --
  8934.     select procedure_text from #proctext order by c1 asc
  8935. END
  8936. go
  8937. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_ins_proc
  8938. GO
  8939. grant exec on dbo.sp_MSscript_sync_ins_proc to public
  8940. go
  8941.  
  8942. --------------------------------------------------------------------------------
  8943. --. sp_MSscript_sync_upd_proc
  8944. --------------------------------------------------------------------------------
  8945.  
  8946. if exists (select * from sysobjects
  8947.     where type = 'P' and name = 'sp_MSscript_sync_upd_proc')
  8948. drop procedure sp_MSscript_sync_upd_proc
  8949. go
  8950. raiserror('Creating procedure sp_MSscript_sync_upd_proc', 0,1)
  8951. go
  8952. create procedure sp_MSscript_sync_upd_proc (
  8953.     @publication sysname, 
  8954.     @article     sysname,
  8955.     @procname    sysname)
  8956. as
  8957. BEGIN
  8958.     declare @source_objid int
  8959.             ,@colname sysname
  8960.             ,@indid int
  8961.             ,@cmd          nvarchar(4000)
  8962.             ,@columns      binary(32)
  8963.             ,@outvars      nvarchar(4000)
  8964.             ,@rc           int
  8965.             ,@error_cmd    tinyint
  8966.             ,@identity_insert bit
  8967.             ,@queued_pub bit
  8968.  
  8969.     set nocount on
  8970.     --
  8971.     -- security check
  8972.     --
  8973.     exec @rc = dbo.sp_MSreplcheck_publish
  8974.     if @@error <> 0 or @rc <> 0
  8975.     begin
  8976.         return (1)
  8977.     end
  8978.     --
  8979.     -- Create temp table
  8980.     --
  8981.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  8982.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  8983.  
  8984.     --
  8985.     -- proc definition
  8986.     --
  8987.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  8988.     if @rc = 0
  8989.         return
  8990.  
  8991.     --
  8992.     -- construct parameter list
  8993.     -- Script bitmap parameter
  8994.     --
  8995.     exec dbo.sp_MSscript_params @source_objid, @columns, null, 1,  @outvars output
  8996.     insert into #proctext(procedure_text) values( N',')
  8997.     exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null
  8998.     insert into #proctext(procedure_text) values( N'
  8999.     ,@bitmap varbinary(4000)')
  9000.  
  9001.     --
  9002.     -- add other parameters and start body of proc
  9003.     --
  9004.     exec dbo.sp_MSscript_procbodystart @queued_pub 
  9005.  
  9006.     --
  9007.     -- script out security check
  9008.     --
  9009.     exec dbo.sp_MSscript_security @publication
  9010.  
  9011.     --
  9012.     -- script the execution mode checks
  9013.     --
  9014.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 2
  9015.  
  9016.     --
  9017.     -- script out subscription validation
  9018.     --
  9019.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  9020.  
  9021.     --
  9022.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  9023.     -- *** Do we need to check this here - 
  9024.     -- *** we should be checking this when creating subscription
  9025.     -- 
  9026.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  9027.     if @rc = 1
  9028.         select @error_cmd = 1
  9029.     else
  9030.     begin
  9031.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  9032.         if (@outvars != null and @indid = 0)
  9033.             -- no insert/update allowed if timestamp/identity col and no unique index
  9034.             select @error_cmd = 1
  9035.         else
  9036.             select @error_cmd = 0        
  9037.     end
  9038.  
  9039.     if (@error_cmd = 0)
  9040.     begin
  9041.         -- Continue generation
  9042.         
  9043.         --
  9044.         -- script update statemnt
  9045.         --
  9046.         exec dbo.sp_MSscript_update_statement @publication, @article, @source_objid, @columns, @queued_pub
  9047.  
  9048.         --
  9049.         -- script queued specific stuff
  9050.         --
  9051.         if (@queued_pub = 1)
  9052.         begin
  9053.             -- Check to see if identity insert must be turned on
  9054.             -- i.e. Does the table has identity that are included in the partition?
  9055.             exec sp_MSis_identity_insert @publication, @article, @identity_insert output
  9056.             --
  9057.             --
  9058.             -- script Conflict resolution block for Subscriber Wins case
  9059.             --
  9060.             exec dbo.sp_MSscript_update_subwins @publication, @article, @source_objid, @columns, @identity_insert
  9061.  
  9062.             --
  9063.             -- script Conflict resolution block for Publisher Wins case
  9064.             --
  9065.             exec dbo.sp_MSscript_update_pubwins @publication, @article, @source_objid, @columns
  9066.         end
  9067.  
  9068.         --
  9069.         -- script closing 
  9070.         --
  9071.         exec dbo.sp_MSscript_endproc @source_objid, 'upd', @columns, @outvars, @queued_pub
  9072.     end
  9073.     else
  9074.     begin
  9075.         --
  9076.         -- Generate error command and finish
  9077.         --
  9078.         insert into #proctext(procedure_text) values( N'
  9079.     exec sp_MSreplraiserror 20516
  9080. END
  9081. ')
  9082.     end
  9083.                   
  9084.     --
  9085.     -- send fragments to client
  9086.     --
  9087.     select procedure_text from #proctext order by c1 asc
  9088. END
  9089. go
  9090. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_upd_proc
  9091. GO
  9092. grant exec on dbo.sp_MSscript_sync_upd_proc to public
  9093. go
  9094.  
  9095. --------------------------------------------------------------------------------
  9096. --. sp_script_reconciliation_insproc
  9097. --------------------------------------------------------------------------------
  9098.  
  9099. if exists (select * from sysobjects
  9100.     where type = 'P' and name = 'sp_script_reconciliation_insproc')
  9101. drop procedure sp_script_reconciliation_insproc
  9102. go
  9103. raiserror('Creating procedure sp_script_reconciliation_insproc', 0,1)
  9104. go
  9105. create procedure sp_script_reconciliation_insproc (
  9106.     @artid int)
  9107. as
  9108. BEGIN
  9109. declare @retcode int
  9110. declare @cmd          nvarchar(4000)
  9111. declare @dest_owner   nvarchar(255)
  9112. declare @dest_tabname sysname
  9113. declare @src_objid    int
  9114. declare @artcolumns   binary(32)
  9115. declare @pkcolumns    binary(32)
  9116. declare @ins_cmd      nvarchar(255)
  9117. declare @dest_proc    sysname
  9118. declare @this_col     int
  9119. declare @art_col      int
  9120. declare @isset        int
  9121.  
  9122. declare @typestring   nvarchar(255)
  9123. declare @spacer       nvarchar(1)
  9124.     , @identity_insert bit
  9125.     
  9126. --
  9127. -- security check
  9128. --
  9129. exec @retcode = dbo.sp_MSreplcheck_publish
  9130. if @@error <> 0 or @retcode <> 0
  9131. begin
  9132.     return (1)
  9133. end
  9134.  
  9135. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  9136. begin
  9137.     raiserror (14155, 16, 1 )
  9138.     return 1
  9139. end
  9140.  
  9141. -------- create temp table for command fragments
  9142.  
  9143. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9144.  
  9145. -------- get sysarticles information
  9146.  
  9147. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  9148.        @src_objid = objid, @artcolumns = columns, @ins_cmd = ins_cmd
  9149. from sysarticles
  9150. where artid = @artid
  9151.  
  9152. if @dest_owner is not null
  9153. begin
  9154.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  9155. end
  9156. else
  9157. begin
  9158.     select @dest_owner = N''
  9159. end
  9160.  
  9161. -- Check to see if identity insert must be turned on
  9162. -- i.e. Does the table has identity that are included in the partition?
  9163. exec sp_MSis_identity_insert null, null, @identity_insert output, @artid
  9164. --
  9165.  
  9166. -------- get dest proc name
  9167.  
  9168. if( 1 != charindex( N'CALL', upper(@ins_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @ins_cmd is null
  9169. begin
  9170.     raiserror (14156, 16, 1 )
  9171.     return 1
  9172. end
  9173.  
  9174. select @dest_proc = substring( @ins_cmd, 6, len( @ins_cmd ) - 4 )
  9175. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  9176.  
  9177. -------- construct parameter list
  9178.  
  9179.  
  9180. select @art_col = 1
  9181. select @spacer = N' '
  9182.  
  9183. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  9184. select colid from syscolumns where id = @src_objid order by colid asc
  9185.  
  9186. OPEN hCColid
  9187.  
  9188. FETCH hCColid INTO @this_col
  9189.  
  9190. WHILE (@@fetch_status <> -1)
  9191. begin
  9192.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  9193.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  9194.    begin
  9195.         if len( @cmd ) > 3000
  9196.         begin
  9197.         insert into #proctext(procedure_text) values( @cmd )
  9198.             select @cmd = N''
  9199.         end
  9200.  
  9201.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  9202.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  9203.         select @art_col = @art_col + 1
  9204.         select @spacer = N','
  9205.    end
  9206.    FETCH hCColid INTO @this_col
  9207. end
  9208. CLOSE hCColid
  9209. DEALLOCATE hCColid
  9210.  
  9211.  
  9212. -- save off cmd fragment
  9213.  
  9214. insert into #proctext(procedure_text) values( @cmd )
  9215.  
  9216. insert into #proctext(procedure_text) values( N'as' )
  9217.  
  9218. ------- construct proc body
  9219.  
  9220. ---- if already exists, apply as update
  9221.  
  9222. insert into #proctext(procedure_text) 
  9223.     values( N'if exists ( select * from ' + @dest_owner + QUOTENAME(@dest_tabname) )
  9224. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  9225. exec dbo.sp_scriptreconwhereclause @src_objid, @pkcolumns, @artcolumns
  9226. insert into #proctext(procedure_text) values( N')' )
  9227. insert into #proctext(procedure_text) values (N'begin')
  9228.  
  9229.  
  9230. if( @artcolumns != @pkcolumns )
  9231. begin
  9232.     -- construct update 
  9233.  
  9234.     select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  9235.  
  9236.     -- create SET clause
  9237.  
  9238.     select @art_col = 1
  9239.     select @spacer = N' '
  9240.  
  9241.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  9242.     select colid from syscolumns where id = @src_objid order by colid asc
  9243.  
  9244.     OPEN hCColid
  9245.  
  9246.     FETCH hCColid INTO @this_col
  9247.  
  9248.     WHILE (@@fetch_status <> -1)
  9249.     begin
  9250.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  9251.         if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  9252.         begin
  9253.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  9254.             if @isset = 0
  9255.             begin
  9256.                 if not (@identity_insert = 1 and 
  9257.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  9258.                 begin
  9259.                     select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  9260.                     select @spacer = N','
  9261.  
  9262.                     if len( @cmd ) > 3000
  9263.                     begin
  9264.                         insert into #proctext(procedure_text) values( @cmd )
  9265.                         select @cmd = N''
  9266.                     end
  9267.                 end
  9268.             end
  9269.             select @art_col = @art_col + 1
  9270.         end
  9271.         FETCH hCColid INTO @this_col
  9272.        end
  9273.     CLOSE hCColid
  9274.     DEALLOCATE hCColid
  9275.  
  9276.     insert into #proctext(procedure_text) values( @cmd )
  9277.  
  9278.     exec dbo.sp_scriptreconwhereclause @src_objid, @pkcolumns, @artcolumns
  9279. end
  9280.  
  9281. -- all article columns are included in the PK, & PK already exists, do nothing
  9282. else 
  9283. begin
  9284.     insert into #proctext(procedure_text ) values( N'return' )
  9285. end
  9286.  
  9287.  
  9288. insert into #proctext(procedure_text) values (N'end')
  9289. insert into #proctext(procedure_text) values (N'else')
  9290. insert into #proctext(procedure_text) values (N'begin')
  9291.  
  9292. ---- normal insert
  9293.  
  9294. -- set identity_insert on
  9295. if @identity_insert = 1
  9296. begin
  9297.     select @cmd = N'
  9298. set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' on'
  9299.     insert into #proctext(procedure_text) values( @cmd )
  9300. end
  9301.  
  9302. -- prepare the column list
  9303.  
  9304. select @cmd = N'insert into ' + @dest_owner + QUOTENAME(@dest_tabname) + N' ('
  9305. select @art_col = 1
  9306. select @spacer = N' '
  9307.  
  9308. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  9309. select colid from syscolumns where id = @src_objid order by colid asc
  9310.  
  9311. OPEN hCColid
  9312.  
  9313. FETCH hCColid INTO @this_col
  9314.  
  9315. WHILE (@@fetch_status <> -1)
  9316. begin
  9317.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  9318.     if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  9319.     begin
  9320.         if len( @cmd ) > 3000
  9321.         begin
  9322.         insert into #proctext(procedure_text) values( @cmd )
  9323.             select @cmd = N''
  9324.         end
  9325.  
  9326.         select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col))  
  9327.         select @art_col = @art_col + 1
  9328.         select @spacer = N','
  9329.     end
  9330.     FETCH hCColid INTO @this_col
  9331. end
  9332. CLOSE hCColid
  9333. DEALLOCATE hCColid
  9334.  
  9335. -- now the data parameter list
  9336.  
  9337. select @cmd = @cmd + N' ) values ('
  9338. select @art_col = 1
  9339. select @spacer = N' '
  9340.  
  9341. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  9342. select colid from syscolumns where id = @src_objid order by colid asc
  9343.  
  9344. OPEN hCColid
  9345.  
  9346. FETCH hCColid INTO @this_col
  9347.  
  9348. WHILE (@@fetch_status <> -1)
  9349. begin
  9350.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  9351.     if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  9352.     begin
  9353.         if len( @cmd ) > 3000
  9354.         begin
  9355.         insert into #proctext(procedure_text) values( @cmd )
  9356.             select @cmd = N''
  9357.         end
  9358.  
  9359.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) 
  9360.         select @art_col = @art_col + 1
  9361.         select @spacer = N','
  9362.     end
  9363.     FETCH hCColid INTO @this_col
  9364. end
  9365. CLOSE hCColid
  9366. DEALLOCATE hCColid
  9367.  
  9368. -- finish up proc body
  9369.  
  9370. select @cmd = @cmd + N' )'
  9371.  
  9372. -- save off cmd fragement
  9373.  
  9374. insert into #proctext(procedure_text) values( @cmd )
  9375.  
  9376. -- set identity_insert off
  9377. if @identity_insert = 1
  9378. begin
  9379.     select @cmd = N'
  9380. set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' off'
  9381.     insert into #proctext(procedure_text) values( @cmd )
  9382. end
  9383.  
  9384. insert into #proctext(procedure_text) values (N'end')
  9385.  
  9386. -- send fragments to client
  9387.  
  9388. select procedure_text from #proctext order by c1 asc
  9389. END
  9390. go
  9391. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_insproc
  9392. GO
  9393. grant exec on dbo.sp_script_reconciliation_insproc to public
  9394. go
  9395.  
  9396. --------------------------------------------------------------------------------
  9397. --. sp_script_reconciliation_delproc
  9398. --------------------------------------------------------------------------------
  9399.  
  9400. if exists (select * from sysobjects
  9401.     where type = 'P' and name = 'sp_script_reconciliation_delproc')
  9402. drop procedure sp_script_reconciliation_delproc
  9403. go
  9404. raiserror('Creating procedure sp_script_reconciliation_delproc', 0,1)
  9405. go
  9406. create procedure sp_script_reconciliation_delproc 
  9407.     @artid int
  9408. )
  9409. as
  9410. begin
  9411.     declare @retcode int
  9412.     declare @cmd          nvarchar(4000)
  9413.     declare @dest_owner   nvarchar(255)
  9414.     declare @dest_tabname sysname
  9415.     declare @src_objid    int
  9416.     declare @pkcolumns    binary(32)
  9417.     declare @del_cmd      nvarchar(255)
  9418.     declare @dest_proc    sysname
  9419.     declare @this_col     int
  9420.     declare @art_col      int
  9421.     declare @isset        int
  9422.  
  9423.     declare @typestring   nvarchar(255)
  9424.     declare @spacer       nvarchar(10)
  9425.  
  9426.     --
  9427.     -- security check
  9428.     --
  9429.     exec @retcode = dbo.sp_MSreplcheck_publish
  9430.     if @@error <> 0 or @retcode <> 0
  9431.     begin
  9432.         return (1)
  9433.     end
  9434.  
  9435.     if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  9436.     begin
  9437.         raiserror (14155, 16, 1 )
  9438.         return 1
  9439.     end
  9440.  
  9441.     -------- create temp table for command fragments
  9442.  
  9443.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9444.  
  9445.     -- get sysarticles information
  9446.  
  9447.     select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  9448.            @src_objid = objid, @del_cmd = del_cmd
  9449.     from sysarticles
  9450.     where artid = @artid
  9451.  
  9452.     if @dest_owner is not null
  9453.     begin
  9454.         select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  9455.     end
  9456.     else
  9457.     begin
  9458.         select @dest_owner = N''
  9459.     end
  9460.  
  9461.     -------- get dest proc name
  9462.  
  9463.     if( 1 != charindex( N'CALL', upper(@del_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @del_cmd is null
  9464.     begin
  9465.         raiserror (14156, 16, 1 )
  9466.         return 1
  9467.     end
  9468.  
  9469.     select @dest_proc = substring( @del_cmd, 6, len( @del_cmd ) - 4 )
  9470.     select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  9471.  
  9472.  
  9473.     -------- construct parameter list
  9474.  
  9475.  
  9476.     select @art_col = 1
  9477.     select @spacer = N' '
  9478.  
  9479.     exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  9480.  
  9481.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  9482.     select colid from syscolumns where id = @src_objid order by colid asc
  9483.  
  9484.     OPEN hCColid
  9485.  
  9486.     FETCH hCColid INTO @this_col
  9487.  
  9488.     WHILE (@@fetch_status <> -1)
  9489.     begin
  9490.        exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  9491.        if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  9492.        begin
  9493.             if len( @cmd ) > 3000
  9494.             begin
  9495.             insert into #proctext(procedure_text) values( @cmd )
  9496.                 select @cmd = N''
  9497.             end
  9498.  
  9499.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  9500.             select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  9501.             select @art_col = @art_col + 1
  9502.             select @spacer = N','
  9503.        end
  9504.         FETCH hCColid INTO @this_col
  9505.     end
  9506.  
  9507.     CLOSE hCColid
  9508.     DEALLOCATE hCColid
  9509.  
  9510.     -- save off 
  9511.  
  9512.     insert into #proctext(procedure_text) values( @cmd )
  9513.     insert into #proctext(procedure_text) values( N'as' )
  9514.  
  9515.     ------- construct proc body
  9516.  
  9517.     insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  9518.  
  9519.     exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  9520.  
  9521.     -- flush to client
  9522.  
  9523.     select procedure_text from #proctext order by c1 asc
  9524. end
  9525. go
  9526. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_delproc
  9527. GO
  9528. grant exec on dbo.sp_script_reconciliation_delproc to public
  9529. go
  9530.  
  9531. --------------------------------------------------------------------------------
  9532. --. sp_script_reconciliation_xdelproc
  9533. --------------------------------------------------------------------------------
  9534.  
  9535. if exists (select * from sysobjects
  9536.     where type = 'P' and name = 'sp_script_reconciliation_xdelproc')
  9537. drop procedure sp_script_reconciliation_xdelproc
  9538. go
  9539. raiserror('Creating procedure sp_script_reconciliation_xdelproc', 0,1)
  9540. go
  9541. create procedure sp_script_reconciliation_xdelproc 
  9542. (
  9543.     @artid int
  9544. )
  9545. as
  9546. begin
  9547.     declare @retcode int
  9548.     declare @cmd          nvarchar(4000)
  9549.     declare @dest_owner   nvarchar(255)
  9550.     declare @dest_tabname sysname
  9551.     declare @src_objid    int
  9552.     declare @columns    binary(32)
  9553.     declare @pkcolumns    binary(32)
  9554.     declare @del_cmd      nvarchar(255)
  9555.     declare @dest_proc    sysname
  9556.     declare @this_col     int
  9557.     declare @art_col      int
  9558.     declare @isset        int
  9559.  
  9560.     declare @typestring   nvarchar(255)
  9561.     declare @spacer       nvarchar(10)
  9562.  
  9563.     --
  9564.     -- security check
  9565.     --
  9566.     exec @retcode = dbo.sp_MSreplcheck_publish
  9567.     if @@error <> 0 or @retcode <> 0
  9568.     begin
  9569.         return (1)
  9570.     end
  9571.  
  9572.     if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  9573.     begin
  9574.         raiserror (14155, 16, 1 )
  9575.         return 1
  9576.     end
  9577.  
  9578.     -------- create temp table for command fragments
  9579.  
  9580.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9581.  
  9582.     -- get sysarticles information
  9583.  
  9584.     select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  9585.            @src_objid = objid, @del_cmd = del_cmd, @columns = columns
  9586.     from sysarticles
  9587.     where artid = @artid
  9588.  
  9589.     if @dest_owner is not null
  9590.     begin
  9591.         select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  9592.     end
  9593.     else
  9594.     begin
  9595.         select @dest_owner = N''
  9596.     end
  9597.  
  9598.     -------- get dest proc name
  9599.  
  9600.     if( 1 != charindex( N'XCALL', upper(@del_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @del_cmd is null
  9601.     begin
  9602.         raiserror (14156, 16, 1 )
  9603.         return 1
  9604.     end
  9605.  
  9606.     select @dest_proc = substring( @del_cmd, 7, len( @del_cmd ) - 5 )
  9607.     select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  9608.  
  9609.     -------- construct parameter list
  9610.  
  9611.  
  9612.     select @art_col = 1
  9613.     select @spacer = N' '
  9614.  
  9615.     exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  9616.  
  9617.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  9618.     select colid from syscolumns where id = @src_objid order by colid asc
  9619.  
  9620.     OPEN hCColid
  9621.  
  9622.     FETCH hCColid INTO @this_col
  9623.  
  9624.     WHILE (@@fetch_status <> -1)
  9625.     begin
  9626.        exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  9627.        if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  9628.        begin
  9629.             if len( @cmd ) > 3000
  9630.             begin
  9631.             insert into #proctext(procedure_text) values( @cmd )
  9632.                 select @cmd = N''
  9633.             end
  9634.  
  9635.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  9636.             select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  9637.             select @art_col = @art_col + 1
  9638.             select @spacer = N','
  9639.        end
  9640.        FETCH hCColid INTO @this_col
  9641.     end
  9642.  
  9643.     CLOSE hCColid
  9644.     DEALLOCATE hCColid
  9645.  
  9646.     -- save off 
  9647.  
  9648.     insert into #proctext(procedure_text) values( @cmd )
  9649.     insert into #proctext(procedure_text) values( N'as' )
  9650.  
  9651.     ------- construct proc body
  9652.  
  9653.     insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  9654.  
  9655.     exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @columns
  9656.  
  9657.     -- flush to client
  9658.  
  9659.     select procedure_text from #proctext order by c1 asc
  9660. end
  9661. go
  9662.  
  9663. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_xdelproc
  9664. GO
  9665. grant exec on dbo.sp_script_reconciliation_xdelproc to public
  9666. go
  9667.  
  9668. --------------------------------------------------------------------------------
  9669. --. sp_scriptinsproc
  9670. --------------------------------------------------------------------------------
  9671.  
  9672. if exists (select * from sysobjects
  9673.     where type = 'P' and name = 'sp_scriptinsproc')
  9674. drop procedure sp_scriptinsproc
  9675. go
  9676. raiserror('Creating procedure sp_scriptinsproc', 0,1)
  9677. go
  9678. create procedure sp_scriptinsproc (
  9679.     @artid int)
  9680. as
  9681. BEGIN
  9682. declare @cmd          nvarchar(4000)
  9683.         ,@dest_owner   nvarchar(255)
  9684.         ,@dest_tabname sysname
  9685.         ,@src_objid    int
  9686.         ,@columns      binary(32)
  9687.         ,@ins_cmd      nvarchar(255)
  9688.         ,@dest_proc    sysname
  9689.         ,@this_col     int
  9690.         ,@art_col      int
  9691.         ,@isset        int
  9692.         ,@pubid          int
  9693.  
  9694.         ,@identity_insert bit
  9695.         ,@rc int
  9696.         ,@colname sysname
  9697.         ,@ccoltype     sysname
  9698.         ,@typestring   nvarchar(255)
  9699.         ,@spacer       nvarchar(1)
  9700.         ,@queued_check bit
  9701.         ,@column_string nvarchar(4000)
  9702.         ,@var_string nvarchar(4000)
  9703.  
  9704. set nocount on
  9705. --
  9706. -- security check
  9707. --
  9708. exec @rc = dbo.sp_MSreplcheck_publish
  9709. if @@error <> 0 or @rc <> 0
  9710. begin
  9711.     return (1)
  9712. end
  9713.  
  9714. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  9715. begin
  9716.     raiserror (14155, 16, 1 )
  9717.     return 1
  9718. end
  9719.  
  9720. -------- create temp table for command fragments and insert column list
  9721.  
  9722. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9723. create table #collisttab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9724.  
  9725. -------- get sysarticles information
  9726.  
  9727. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  9728.        @src_objid = objid, @columns = columns, @ins_cmd = ins_cmd,
  9729.        @pubid = pubid
  9730. from sysarticles
  9731. where artid = @artid
  9732.  
  9733. -- Check to see if identity insert must be turned on
  9734. -- i.e. Does the table has identity that are included in the partition?
  9735. exec sp_MSis_identity_insert null, null, @identity_insert output, @artid
  9736. --
  9737.  
  9738. if @dest_owner is not null
  9739. begin
  9740.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  9741. end
  9742. else
  9743. begin
  9744.     select @dest_owner = N''
  9745. end
  9746.  
  9747. -- Check if this is a queued publication
  9748. select @queued_check = ISNULL(allow_queued_tran, 0) 
  9749. from syspublications
  9750. where pubid = @pubid
  9751.  
  9752. -------- get dest proc name
  9753.  
  9754. if( 1 != charindex( N'CALL', upper(@ins_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @ins_cmd is null
  9755. begin
  9756.     raiserror (14156, 16, 1 )
  9757.     return 1
  9758. end
  9759.  
  9760. select @dest_proc = substring( @ins_cmd, 6, len( @ins_cmd ) - 4 )
  9761. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  9762. insert into #proctext(procedure_text) values( @cmd )
  9763. insert into #proctext(procedure_text) values( N'go' )
  9764. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  9765.  
  9766. -------- construct parameter list
  9767.  
  9768.  
  9769. select @art_col = 1
  9770. select @spacer = N' '
  9771.  
  9772. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  9773. select colid from syscolumns where id = @src_objid order by colid asc
  9774.  
  9775. OPEN hCColid
  9776.  
  9777. FETCH hCColid INTO @this_col
  9778.  
  9779. WHILE (@@fetch_status <> -1)
  9780. begin
  9781.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  9782.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  9783.    begin
  9784.         if len( @cmd ) > 3000
  9785.         begin
  9786.         insert into #proctext(procedure_text) values( @cmd )
  9787.             select @cmd = N''
  9788.         end
  9789.  
  9790.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  9791.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  9792.         select @art_col = @art_col + 1
  9793.         select @spacer = N','
  9794.    end
  9795.    FETCH hCColid INTO @this_col
  9796. end
  9797.  
  9798. CLOSE hCColid
  9799. DEALLOCATE hCColid
  9800.  
  9801. -- save off cmd fragment
  9802.  
  9803. insert into #proctext(procedure_text) values( @cmd )
  9804.  
  9805. select @cmd = N'
  9806. AS
  9807. BEGIN
  9808. '
  9809. insert into #proctext(procedure_text) values( @cmd )
  9810.  
  9811. ------- construct proc body
  9812.  
  9813. -- Generate strings for col names and variables
  9814. select @art_col = 0
  9815. select @spacer = N' '
  9816.  
  9817. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  9818. select colid from syscolumns where id = @src_objid order by colid asc
  9819.  
  9820. OPEN hCColid
  9821.  
  9822. FETCH hCColid INTO @this_col
  9823.  
  9824. WHILE (@@fetch_status <> -1)
  9825. begin
  9826.     exec @rc = dbo.sp_MSget_colinfo @src_objid, @this_col, @columns, 1, @colname output, @ccoltype output
  9827.     if @rc = 0  and EXISTS (select name from syscolumns where id=@src_objid and colid=@this_col and iscomputed<>1)
  9828.     begin
  9829.         select @art_col = @art_col + 1
  9830.         if (@art_col = 1)
  9831.         begin
  9832.             select @column_string = QUOTENAME(@colname)
  9833.             select @var_string = N'@c' + cast(@art_col as nvarchar(4))
  9834.         end
  9835.         else
  9836.         begin
  9837.             select @column_string = @column_string + N', ' + QUOTENAME(@colname)
  9838.             select @var_string = @var_string + N', @c' + cast(@art_col as nvarchar(4))
  9839.         end
  9840.  
  9841.         -- transfer column list string to table if too large
  9842.         if (len(@column_string) > 3000)
  9843.         begin
  9844.             insert into #collisttab(procedure_text) values( @column_string )
  9845.             select @column_string = ' '
  9846.         end
  9847.     end
  9848.     FETCH hCColid INTO @this_col
  9849. end
  9850.  
  9851. CLOSE hCColid
  9852. DEALLOCATE hCColid
  9853.  
  9854. -- insert the remaining strings for column list and where clause
  9855. insert into #collisttab(procedure_text) values( @column_string )
  9856.  
  9857. --
  9858. -- If we are a part of queued publication then 
  9859. -- insert only if PK or other unique key(s) do not exist
  9860. --
  9861. if (@queued_check = 1)
  9862. begin
  9863.     select @cmd = N'
  9864. if not exists (select * from ' + @dest_owner + QUOTENAME(@dest_tabname) + N' '
  9865.     insert into #proctext(procedure_text) values( @cmd )
  9866.     exec @rc = sp_replscriptuniquekeywhereclause @tabid = @src_objid
  9867.                                                         ,@columns = @columns
  9868.                                                         ,@prefix = '@c' 
  9869.                                                         ,@mode = 1
  9870.     if (@@error != 0 or @rc != 0)
  9871.         return 1
  9872.     select @cmd = N')
  9873. BEGIN'
  9874.     insert into #proctext(procedure_text) values( @cmd )
  9875. end
  9876.  
  9877. -- set identity_insert on
  9878. if @identity_insert = 1
  9879. begin
  9880.     select @cmd = N'
  9881.     set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' on'
  9882.     insert into #proctext(procedure_text) values( @cmd )
  9883. end
  9884.  
  9885. --
  9886. -- prepare the insert statement now
  9887. --
  9888. select @cmd = N'
  9889. insert into ' +  @dest_owner + QUOTENAME(@dest_tabname)  + N'( '
  9890. insert into #proctext(procedure_text) values( @cmd )
  9891. insert into #proctext(procedure_text) 
  9892.     select procedure_text from #collisttab order by c1 asc
  9893. select @cmd = N' )'
  9894. insert into #proctext(procedure_text) values( @cmd )
  9895. if @art_col > 0
  9896. begin
  9897.     select @cmd = N'
  9898. values ( '
  9899.     insert into #proctext(procedure_text) values( @cmd )
  9900.     insert into #proctext(procedure_text) values( @var_string )
  9901.     select @cmd = N' )
  9902. '
  9903.     insert into #proctext(procedure_text) values( @cmd )
  9904. end
  9905.  
  9906. -- set identity_insert off
  9907. if @identity_insert = 1
  9908. begin
  9909.     select @cmd = N'
  9910.     set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' off'
  9911.     insert into #proctext(procedure_text) values( @cmd )
  9912. end
  9913.  
  9914. --
  9915. -- If we are a part of queued publication then 
  9916. -- add the block delimiter
  9917. --
  9918. drop table #collisttab
  9919. if (@queued_check = 1)
  9920. begin
  9921.     select @cmd = N'
  9922. END
  9923. END'
  9924. end
  9925. else
  9926.     select @cmd = N'
  9927. END'
  9928. insert into #proctext(procedure_text) values( @cmd )
  9929.  
  9930. -- send fragements to client
  9931.  
  9932. select procedure_text from #proctext order by c1 asc
  9933. END
  9934. go
  9935. EXEC dbo.sp_MS_marksystemobject sp_scriptinsproc
  9936. GO
  9937. grant exec on dbo.sp_scriptinsproc to public
  9938. go
  9939.  
  9940. --------------------------------------------------------------------------------
  9941. --. sp_scriptdelproc
  9942. --------------------------------------------------------------------------------
  9943.  
  9944. if exists (select * from sysobjects
  9945.     where type = 'P' and name = 'sp_scriptdelproc')
  9946. drop procedure sp_scriptdelproc
  9947. go
  9948. raiserror('Creating procedure sp_scriptdelproc', 0,1)
  9949. go
  9950. create procedure sp_scriptdelproc 
  9951. (
  9952.     @artid int
  9953. )
  9954. as
  9955. begin
  9956.     declare @retcode int
  9957.     declare @cmd          nvarchar(4000)
  9958.     declare @dest_owner   nvarchar(255)
  9959.     declare @dest_tabname sysname
  9960.     declare @src_objid    int
  9961.     declare @pkcolumns    binary(32)
  9962.     declare @del_cmd      nvarchar(255)
  9963.     declare @dest_proc    sysname
  9964.     declare @this_col     int
  9965.     declare @art_col      int
  9966.     declare @isset        int, @pubid int
  9967.  
  9968.     declare @typestring   nvarchar(255)
  9969.     declare @spacer       nvarchar(10)
  9970.  
  9971.     --
  9972.     -- security check
  9973.     --
  9974.     exec @retcode = dbo.sp_MSreplcheck_publish
  9975.     if @@error <> 0 or @retcode <> 0
  9976.     begin
  9977.         return (1)
  9978.     end
  9979.     
  9980.     if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  9981.     begin
  9982.         raiserror (14155, 16, 1 )
  9983.         return 1
  9984.     end
  9985.  
  9986.     -------- create temp table for command fragments
  9987.  
  9988.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9989.  
  9990.     -- get sysarticles information
  9991.  
  9992.     select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  9993.            @src_objid = objid, @del_cmd = del_cmd, @pubid = pubid
  9994.     from sysarticles
  9995.     where artid = @artid
  9996.  
  9997.     if @dest_owner is not null
  9998.     begin
  9999.         select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  10000.     end
  10001.     else
  10002.     begin
  10003.         select @dest_owner = N''
  10004.     end
  10005.  
  10006.     -------- get dest proc name
  10007.  
  10008.     if( 1 != charindex( N'CALL', upper(@del_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @del_cmd is null
  10009.     begin
  10010.         raiserror (14156, 16, 1 )
  10011.         return 1
  10012.     end
  10013.  
  10014.     select @dest_proc = substring( @del_cmd, 6, len( @del_cmd ) - 4 )
  10015.     select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  10016.     insert into #proctext(procedure_text) values( @cmd )
  10017.     insert into #proctext(procedure_text) values( N'go' )
  10018.     select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  10019.  
  10020.     -------- construct parameter list
  10021.  
  10022.  
  10023.     select @art_col = 1
  10024.     select @spacer = N' '
  10025.  
  10026.     exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  10027.  
  10028.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10029.     select colid from syscolumns where id = @src_objid order by colid asc
  10030.  
  10031.     OPEN hCColid
  10032.  
  10033.     FETCH hCColid INTO @this_col
  10034.  
  10035.     WHILE (@@fetch_status <> -1)
  10036.     begin
  10037.        exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  10038.        if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  10039.        begin
  10040.             if len( @cmd ) > 3000
  10041.             begin
  10042.             insert into #proctext(procedure_text) values( @cmd )
  10043.                 select @cmd = N''
  10044.             end
  10045.  
  10046.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  10047.             select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  10048.             select @art_col = @art_col + 1
  10049.             select @spacer = N','
  10050.        end
  10051.         FETCH hCColid INTO @this_col
  10052.     end
  10053.  
  10054.     CLOSE hCColid
  10055.     DEALLOCATE hCColid
  10056.  
  10057.     -- save off 
  10058.  
  10059.     insert into #proctext(procedure_text) values( @cmd )
  10060.     insert into #proctext(procedure_text) values( N'as' )
  10061.  
  10062.     ------- construct proc body
  10063.  
  10064.     insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  10065.  
  10066.     exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  10067.  
  10068.     if exists (select * from syspublications where pubid = @pubid and allow_queued_tran = 0)
  10069.         exec dbo.sp_MSscript_missing_row_check
  10070.     -- flush to client
  10071.  
  10072.     select procedure_text from #proctext order by c1 asc
  10073. end
  10074. go
  10075. EXEC dbo.sp_MS_marksystemobject sp_scriptdelproc
  10076. GO
  10077. grant exec on dbo.sp_scriptdelproc to public
  10078. go
  10079.  
  10080. --------------------------------------------------------------------------------
  10081. --. sp_scriptxdelproc
  10082. --------------------------------------------------------------------------------
  10083.  
  10084. if exists (select * from sysobjects
  10085.     where type = 'P' and name = 'sp_scriptxdelproc')
  10086. drop procedure sp_scriptxdelproc
  10087. go
  10088. raiserror('Creating procedure sp_scriptxdelproc', 0,1)
  10089. go
  10090. create procedure sp_scriptxdelproc 
  10091. (
  10092.     @artid int
  10093. )
  10094. as
  10095. begin
  10096.     declare @retcode int
  10097.     declare @cmd          nvarchar(4000)
  10098.     declare @dest_owner   nvarchar(255)
  10099.     declare @dest_tabname sysname
  10100.     declare @src_objid    int
  10101.     declare @columns    binary(32)
  10102.     declare @pkcolumns    binary(32)
  10103.     declare @del_cmd      nvarchar(255)
  10104.     declare @dest_proc    sysname
  10105.     declare @this_col     int
  10106.     declare @art_col      int
  10107.     declare @isset        int
  10108.     declare @pubid          int
  10109.     declare @typestring   nvarchar(255)
  10110.     declare @spacer       nvarchar(10)
  10111.     declare @queued_check bit
  10112.             ,@qwhere_string nvarchar(4000)
  10113.  
  10114.     --
  10115.     -- security check
  10116.     --
  10117.     exec @retcode = dbo.sp_MSreplcheck_publish
  10118.     if @@error <> 0 or @retcode <> 0
  10119.     begin
  10120.         return (1)
  10121.     end
  10122.     
  10123.     if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  10124.     begin
  10125.         raiserror (14155, 16, 1 )
  10126.         return 1
  10127.     end
  10128.  
  10129.     -------- create temp table for command fragments
  10130.  
  10131.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  10132.  
  10133.     -- get sysarticles information
  10134.  
  10135.     select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  10136.            @src_objid = objid, @del_cmd = del_cmd, @columns = columns
  10137.     from sysarticles
  10138.     where artid = @artid
  10139.  
  10140.     if @dest_owner is not null
  10141.     begin
  10142.         select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  10143.     end
  10144.     else
  10145.     begin
  10146.         select @dest_owner = N''
  10147.     end
  10148.  
  10149.     -- Check if this is a queued publication
  10150.     select @queued_check = ISNULL(allow_queued_tran, 0) 
  10151.     from syspublications
  10152.     where pubid = @pubid
  10153.  
  10154.     -------- get dest proc name
  10155.  
  10156.     if( 1 != charindex( N'XCALL', upper(@del_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @del_cmd is null
  10157.     begin
  10158.         raiserror (14156, 16, 1 )
  10159.         return 1
  10160.     end
  10161.  
  10162.     select @dest_proc = substring( @del_cmd, 7, len( @del_cmd ) - 5 )
  10163.     select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  10164.     insert into #proctext(procedure_text) values( @cmd )
  10165.     insert into #proctext(procedure_text) values( N'go' )
  10166.     select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  10167.  
  10168.     -------- construct parameter list
  10169.  
  10170.  
  10171.     select @art_col = 1
  10172.     select @spacer = N' '
  10173.  
  10174.     exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  10175.  
  10176.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10177.     select colid from syscolumns where id = @src_objid order by colid asc
  10178.  
  10179.     OPEN hCColid
  10180.  
  10181.     FETCH hCColid INTO @this_col
  10182.  
  10183.     WHILE (@@fetch_status <> -1)
  10184.     begin
  10185.        exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  10186.        if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  10187.        begin
  10188.             if len( @cmd ) > 3000
  10189.             begin
  10190.             insert into #proctext(procedure_text) values( @cmd )
  10191.                 select @cmd = N''
  10192.             end
  10193.  
  10194.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  10195.             select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  10196.  
  10197.             --
  10198.             -- Queued processing:if this is the row version column : need to add to where clause
  10199.             --
  10200.             if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  10201.                 select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )
  10202.  
  10203.             select @art_col = @art_col + 1
  10204.             select @spacer = N','
  10205.        end
  10206.        FETCH hCColid INTO @this_col
  10207.     end
  10208.  
  10209.     CLOSE hCColid
  10210.     DEALLOCATE hCColid
  10211.  
  10212.     -- save off 
  10213.  
  10214.     insert into #proctext(procedure_text) values( @cmd )
  10215.     insert into #proctext(procedure_text) values( N'as' )
  10216.  
  10217.     ------- construct proc body
  10218.  
  10219.     insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  10220.  
  10221.     exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @columns
  10222.     if (@queued_check = 1)
  10223.         insert into #proctext(procedure_text) values( @qwhere_string )
  10224.     else
  10225.         exec dbo.sp_MSscript_missing_row_check
  10226.  
  10227.     -- flush to client
  10228.  
  10229.     select procedure_text from #proctext order by c1 asc
  10230. end
  10231. go
  10232. EXEC dbo.sp_MS_marksystemobject sp_scriptxdelproc
  10233. GO
  10234. grant exec on dbo.sp_scriptxdelproc to public
  10235. go
  10236.  
  10237. --------------------------------------------------------------------------------
  10238. --. sp_scriptupdproc
  10239. --------------------------------------------------------------------------------
  10240.  
  10241. if exists (select * from sysobjects
  10242.     where type = 'P' and name = 'sp_scriptupdproc')
  10243. drop procedure sp_scriptupdproc
  10244. go
  10245. raiserror('Creating procedure sp_scriptupdproc', 0,1)
  10246. go
  10247. create procedure sp_scriptupdproc 
  10248. (
  10249.     @artid int
  10250. )
  10251. as
  10252. begin
  10253.     declare @retcode int
  10254.     declare @cmd          nvarchar(4000)
  10255.     declare @dest_owner   nvarchar(255)
  10256.     declare @dest_tabname sysname
  10257.     declare @src_objid    int
  10258.     declare @artcolumns   binary(32)
  10259.     declare @pkcolumns    binary(32)
  10260.     declare @upd_cmd      nvarchar(255)
  10261.     declare @dest_proc    sysname
  10262.     declare @this_col     int
  10263.     declare @art_col      int
  10264.     declare @pkart_col    int
  10265.     declare @isset        int
  10266.     declare @pkcomputed   int
  10267.     declare @typestring   nvarchar(255)
  10268.     declare @spacer       nvarchar(10)
  10269.     declare @pubid        int, @allow_queued_tran bit, @need_end bit
  10270.  
  10271.     --
  10272.     -- security check
  10273.     --
  10274.     exec @retcode = dbo.sp_MSreplcheck_publish
  10275.     if @@error <> 0 or @retcode <> 0
  10276.     begin
  10277.         return (1)
  10278.     end
  10279.     select @need_end = 0
  10280.  
  10281.     if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  10282.     begin
  10283.         raiserror (14155, 16, 1 )
  10284.         return 1
  10285.     end
  10286.  
  10287.     -------- create temp table for command fragments
  10288.  
  10289.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  10290.  
  10291.     -------- get sysarticles information
  10292.  
  10293.     select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  10294.            @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd
  10295.     from sysarticles
  10296.     where artid = @artid
  10297.  
  10298.     if @dest_owner is not null
  10299.     begin
  10300.         select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  10301.     end
  10302.     else
  10303.     begin
  10304.         select @dest_owner = N''
  10305.     end
  10306.  
  10307.     -------- get dest proc name
  10308.  
  10309.     if( 1 != charindex( N'CALL', upper(@upd_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @upd_cmd is null
  10310.     begin
  10311.         raiserror (14156, 16, 1 )
  10312.         return 1
  10313.     end
  10314.  
  10315.     select @allow_queued_tran = allow_queued_tran from syspublications where pubid = @pubid 
  10316.  
  10317.     declare @keep_identity bit
  10318.     if @allow_queued_tran = 1 and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  10319.         select @keep_identity = 1
  10320.     else
  10321.         select @keep_identity = 0
  10322.  
  10323.     select @dest_proc = substring( @upd_cmd, 6, len( @upd_cmd ) - 4 )
  10324.     select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  10325.     insert into #proctext(procedure_text) values( @cmd )
  10326.     insert into #proctext(procedure_text) values( N'go' )
  10327.     insert into #proctext( procedure_text ) values (  N'create procedure ' + QUOTENAME(@dest_proc) + N' ')
  10328.  
  10329.     -------- construct parameter list
  10330.  
  10331.     exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  10332.  
  10333.     exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, @pkcolumns
  10334.  
  10335.     insert into #proctext(procedure_text) values ( N'as' )
  10336.  
  10337.     -------- now create the update statement
  10338.  
  10339.     -- construct test to see if pk has changed 
  10340.     -- only do this if the article has columns not included in the pk
  10341.  
  10342.     exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  10343.  
  10344.     declare @pk_is_identity bit
  10345.     select @pk_is_identity = 0
  10346.  
  10347.     if @artcolumns != @pkcolumns and @pkcomputed = 0
  10348.     begin
  10349.         select @cmd = N'if'
  10350.  
  10351.         select @art_col = 1
  10352.         select @pkart_col = 1
  10353.         select @spacer = ' '
  10354.  
  10355.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10356.         select colid from syscolumns where id = @src_objid order by colid asc
  10357.  
  10358.         OPEN hCColid
  10359.  
  10360.         FETCH hCColid INTO @this_col
  10361.  
  10362.         select @pk_is_identity = 1
  10363.         WHILE (@@fetch_status <> -1)
  10364.         begin
  10365.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  10366.             if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  10367.             begin
  10368.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  10369.                 if @isset != 0
  10370.                 begin
  10371.                     if not (@keep_identity = 1 and 
  10372.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  10373.                     begin
  10374.                         select @pk_is_identity = 0
  10375.                         select @cmd = @cmd + @spacer + N'@c'+convert( nvarchar, @art_col ) + N' = @pkc' + convert( nvarchar, @pkart_col ) 
  10376.                         select @spacer = N' and '
  10377.                         select @pkart_col = @pkart_col + 1
  10378.                         if len( @cmd ) > 3000
  10379.                         begin
  10380.                         insert into #proctext(procedure_text) values( @cmd )
  10381.                             select @cmd = N''
  10382.                         end
  10383.                     end
  10384.                 end
  10385.                 select @art_col = @art_col + 1
  10386.             end
  10387.             FETCH hCColid INTO @this_col
  10388.         end
  10389.  
  10390.         CLOSE hCColid
  10391.         DEALLOCATE hCColid
  10392.  
  10393.         if @pk_is_identity = 0
  10394.         begin
  10395.             insert into #proctext(procedure_text) values( @cmd )
  10396.  
  10397.             insert into #proctext(procedure_text) values( N'begin' )
  10398.  
  10399.             -- construct update if pk hasn't changed
  10400.  
  10401.             select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  10402.  
  10403.             -- create SET clause
  10404.  
  10405.             select @art_col = 1
  10406.             select @spacer = N' '
  10407.  
  10408.             DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10409.             select colid from syscolumns where id = @src_objid order by colid asc
  10410.  
  10411.             OPEN hCColid
  10412.  
  10413.             FETCH hCColid INTO @this_col
  10414.             WHILE (@@fetch_status <> -1)
  10415.             begin
  10416.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  10417.                 if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  10418.                 begin
  10419.                     exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  10420.                     if @isset = 0
  10421.                     begin
  10422.                         if not (@keep_identity = 1 and 
  10423.                             columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  10424.                         begin
  10425.                             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  10426.                             select @spacer = N','
  10427.  
  10428.                             if len( @cmd ) > 3000
  10429.                             begin
  10430.                                 insert into #proctext(procedure_text) values( @cmd )
  10431.                                 select @cmd = N''
  10432.                             end
  10433.                         end
  10434.                     end
  10435.                     select @art_col = @art_col + 1
  10436.                 end
  10437.                 FETCH hCColid INTO @this_col
  10438.             end
  10439.             CLOSE hCColid
  10440.             DEALLOCATE hCColid
  10441.  
  10442.             insert into #proctext(procedure_text) values( @cmd )
  10443.  
  10444.             exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  10445.  
  10446.             if @allow_queued_tran <> 1
  10447.                 exec dbo.sp_MSscript_missing_row_check
  10448.  
  10449.             insert into #proctext(procedure_text) values( N'end' )
  10450.             insert into #proctext(procedure_text) values( N'else' )
  10451.             insert into #proctext(procedure_text) values( N'begin' )
  10452.  
  10453.             select @need_end = 1
  10454.  
  10455.         end
  10456.     end -- end if artcols != pkcols
  10457.  
  10458.  
  10459.     -- construct update if pk has changed
  10460.  
  10461.     select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  10462.  
  10463.     -- create SET clause
  10464.  
  10465.     select @art_col = 1
  10466.     select @spacer = N' '
  10467.  
  10468.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10469.     select colid from syscolumns where id = @src_objid order by colid asc
  10470.  
  10471.     OPEN hCColid
  10472.  
  10473.     FETCH hCColid INTO @this_col
  10474.     WHILE (@@fetch_status <> -1)
  10475.     begin
  10476.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  10477.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  10478.         begin
  10479.             if not (@keep_identity = 1 and 
  10480.                 columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  10481.             begin
  10482.                 select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  10483.                 select @spacer = N','
  10484.  
  10485.                 if len( @cmd ) > 3000
  10486.                 begin
  10487.                 insert into #proctext(procedure_text) values( @cmd )
  10488.                     select @cmd = N''
  10489.                 end
  10490.             end
  10491.             select @art_col = @art_col + 1
  10492.         end
  10493.         FETCH hCColid INTO @this_col
  10494.     end
  10495.  
  10496.     CLOSE hCColid
  10497.     DEALLOCATE hCColid
  10498.  
  10499.     insert into #proctext(procedure_text) values( @cmd )
  10500.  
  10501.     exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  10502.  
  10503.     if @allow_queued_tran <> 1
  10504.         exec dbo.sp_MSscript_missing_row_check
  10505.  
  10506.     if @need_end = 1
  10507.         insert into #proctext(procedure_text) values( N'end' )
  10508.     -- flush to client
  10509.  
  10510.     select procedure_text from #proctext order by c1 asc
  10511. end
  10512. go
  10513. EXEC dbo.sp_MS_marksystemobject sp_scriptupdproc
  10514. GO
  10515. grant exec on dbo.sp_scriptupdproc to public
  10516. go
  10517.  
  10518. --------------------------------------------------------------------------------
  10519. --. sp_scriptmappedupdproc
  10520. --------------------------------------------------------------------------------
  10521.  
  10522. if exists (select * from sysobjects
  10523.     where type = 'P' and name = 'sp_scriptmappedupdproc')
  10524. drop procedure sp_scriptmappedupdproc
  10525. go
  10526. raiserror('Creating procedure sp_scriptmappedupdproc', 0,1)
  10527. go
  10528. create procedure sp_scriptmappedupdproc 
  10529. (
  10530.     @artid int
  10531. )
  10532. as
  10533. begin
  10534.     declare @retcode int
  10535.     declare @cmd          nvarchar(4000)
  10536.     declare @dest_owner   nvarchar(255)
  10537.     declare @dest_tabname sysname
  10538.     declare @src_objid    int
  10539.     declare @artcolumns   binary(32)
  10540.     declare @pkcolumns    binary(32)
  10541.     declare @upd_cmd      nvarchar(255)
  10542.     declare @dest_proc    sysname
  10543.     declare @art_cols     int
  10544.     declare @this_col     int
  10545.     declare @art_col      int
  10546.     declare @pkart_col    int
  10547.     declare @isset        int
  10548.     declare @bytestr      nvarchar(10)
  10549.     declare @bitstr       nvarchar(10)
  10550.     declare @typestring   nvarchar(255)
  10551.     declare @spacer       nvarchar(10)
  10552.     declare @update_created  bit
  10553.     declare @pkcomputed   int
  10554.     declare @pubid        int, @allow_queued_tran bit
  10555.  
  10556.     --
  10557.     -- security check
  10558.     --
  10559.     exec @retcode = dbo.sp_MSreplcheck_publish
  10560.     if @@error <> 0 or @retcode <> 0
  10561.     begin
  10562.         return (1)
  10563.     end
  10564.     select @update_created     = 0
  10565.  
  10566.     if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  10567.     begin
  10568.         raiserror (14155, 16, 1 )
  10569.         return 1
  10570.     end
  10571.  
  10572.     -------- create temp table for command fragments
  10573.  
  10574.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  10575.  
  10576.     -------- get sysarticles information
  10577.  
  10578.     select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  10579.            @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd,
  10580.            @pubid = pubid
  10581.     from sysarticles
  10582.     where artid = @artid
  10583.  
  10584.     if @dest_owner is not null
  10585.     begin
  10586.         select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  10587.     end
  10588.     else
  10589.     begin
  10590.         select @dest_owner = N''
  10591.     end
  10592.  
  10593.     -------- get dest proc name
  10594.  
  10595.     if( 1 != charindex( N'MCALL', upper(@upd_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @upd_cmd is null
  10596.     begin
  10597.         raiserror (14156, 16, 1 )
  10598.         return 1
  10599.     end
  10600.  
  10601.     select @allow_queued_tran = allow_queued_tran from syspublications where pubid = @pubid 
  10602.  
  10603.     declare @keep_identity bit
  10604.     if @allow_queued_tran = 1 and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  10605.         select @keep_identity = 1
  10606.     else
  10607.         select @keep_identity = 0
  10608.  
  10609.     select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 )
  10610.     select @cmd = N'if exists (select * from sysobjects where type = ''P''  and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  10611.     insert into #proctext(procedure_text) values( @cmd )
  10612.     insert into #proctext(procedure_text) values( N'go' )
  10613.     insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ' )
  10614.       
  10615.  
  10616.     -------- construct parameter list
  10617.  
  10618.     exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  10619.  
  10620.     exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, @pkcolumns
  10621.  
  10622.     ----- add changed data bitmap
  10623.  
  10624.     select @art_col = 1
  10625.  
  10626.  
  10627.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10628.     select colid from syscolumns where id = @src_objid order by colid asc
  10629.  
  10630.     OPEN hCColid
  10631.  
  10632.     FETCH hCColid INTO @this_col
  10633.  
  10634.     WHILE (@@fetch_status <> -1)
  10635.     begin
  10636.        exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  10637.        if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  10638.        begin
  10639.             select @art_col = @art_col + 1
  10640.        end
  10641.        FETCH hCColid INTO @this_col
  10642.     end
  10643.     CLOSE hCColid
  10644.     DEALLOCATE hCColid
  10645.  
  10646.     -- Note that bitmap size is based on number of article columns
  10647.     -- (computed by loop above) not source table columns
  10648.  
  10649.     select @cmd = N',@bitmap binary(' + convert(nvarchar,1+(@art_col-1) / 8) + N')'
  10650.  
  10651.     insert into #proctext(procedure_text) values( @cmd )
  10652.     insert into #proctext(procedure_text) values( N'as' )
  10653.  
  10654.  
  10655.     -- construct IF statement to examine colbitmap and determine if a 
  10656.     -- primary key column has been updated.  
  10657.  
  10658.     -- do this only if the article contains columns not included in the pk
  10659.     -- and at least one of the columns in the PK is real ( i.e. not computed )
  10660.  
  10661.     -- note that if all the article columns are PK columns, we will
  10662.     -- construct the 'update all columns including PK columns' statement
  10663.     -- w/o a preceeding IF, and we will NOT construct the 'only update non-pk columns' 
  10664.     -- part of the procedure
  10665.  
  10666.     -- also note that this is pretty much worthless since 7.0 and above are
  10667.     -- guaranteed to NEVER generate an UPDATE if a PK columns is updated... oh well.
  10668.     declare @pk_is_identity bit
  10669.     select @pk_is_identity = 0
  10670.  
  10671.     exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  10672.  
  10673.     if @artcolumns != @pkcolumns and @pkcomputed = 0
  10674.     begin
  10675.         select @art_col = 1
  10676.         select @spacer = N' '
  10677.  
  10678.         select @cmd = N'if'
  10679.  
  10680.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10681.         select colid from syscolumns where id = @src_objid order by colid asc
  10682.  
  10683.         OPEN hCColid
  10684.  
  10685.         FETCH hCColid INTO @this_col
  10686.  
  10687.         select @pk_is_identity = 1
  10688.  
  10689.         WHILE (@@fetch_status <> -1)
  10690.         begin
  10691.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  10692.             if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  10693.             begin 
  10694.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  10695.                 if @isset != 0
  10696.                 begin
  10697.                     if not (@keep_identity = 1 and 
  10698.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  10699.                     begin
  10700.                         select @pk_is_identity = 0
  10701.                         select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  10702.                         select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  10703.  
  10704.                         select @cmd = @cmd + @spacer + N'substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  10705.                                  N' = ' + @bitstr 
  10706.                     
  10707.                         select @spacer = N' or '
  10708.  
  10709.                         if len( @cmd ) > 3000
  10710.                         begin
  10711.                             insert into #proctext(procedure_text) values( @cmd )
  10712.                             select @cmd = N''
  10713.                         end
  10714.                     end
  10715.                 end
  10716.                 select @art_col = @art_col + 1
  10717.             end
  10718.             FETCH hCColid INTO @this_col
  10719.         end
  10720.         CLOSE hCColid
  10721.         DEALLOCATE hCColid
  10722.  
  10723.         if @pk_is_identity = 0
  10724.             insert into #proctext(procedure_text) values( @cmd )
  10725.  
  10726.     end  -- if artcolumns != pkcolumns
  10727.  
  10728.     -- construct update statement including PK columns
  10729.  
  10730.     insert into #proctext(procedure_text) values( N'begin' )
  10731.  
  10732.     insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' )
  10733.  
  10734.     -- create SET clause consisting of CASE statements
  10735.  
  10736.     select @art_col = 1
  10737.     select @spacer = N''
  10738.  
  10739.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10740.     select colid from syscolumns where id = @src_objid order by colid asc
  10741.  
  10742.     OPEN hCColid
  10743.  
  10744.     FETCH hCColid INTO @this_col
  10745.  
  10746.     WHILE (@@fetch_status <> -1)
  10747.     begin
  10748.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  10749.         if @isset != 0  and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  10750.         begin
  10751.             if not (@keep_identity = 1 and 
  10752.                 columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  10753.             begin
  10754.                 select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  10755.                 select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  10756.  
  10757.                 insert into #proctext(procedure_text) values (
  10758.                      @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  10759.                      N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + 
  10760.                      N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' )
  10761.  
  10762.                 select @spacer = ',' 
  10763.             end
  10764.  
  10765.             select @art_col = @art_col + 1
  10766.         end
  10767.         FETCH hCColid INTO @this_col
  10768.     end
  10769.     CLOSE hCColid
  10770.     DEALLOCATE hCColid
  10771.  
  10772.     -- create where clause
  10773.  
  10774.     exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  10775.  
  10776.     if @allow_queued_tran <> 1
  10777.         exec dbo.sp_MSscript_missing_row_check
  10778.  
  10779.     -- construct UPDATE that does not set PK cols
  10780.     -- only do this if the article contains columns that are not included
  10781.     -- in the pk
  10782.  
  10783.     if @artcolumns != @pkcolumns  and @pkcomputed = 0 and @pk_is_identity = 0
  10784.     begin
  10785.  
  10786.         -- create SET clause consisting of CASE statements
  10787.  
  10788.         select @art_col = 1
  10789.         select @spacer = N''
  10790.  
  10791.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10792.         select colid from syscolumns where id = @src_objid order by colid asc
  10793.  
  10794.         OPEN hCColid
  10795.  
  10796.         FETCH hCColid INTO @this_col
  10797.  
  10798.         WHILE (@@fetch_status <> -1)
  10799.         begin
  10800.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  10801.             if @isset != 0  and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  10802.             begin
  10803.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns 
  10804.                 if @isset = 0 
  10805.                 begin
  10806.                     if not (@keep_identity = 1 and 
  10807.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  10808.                     begin
  10809.                         if (@update_created = 0)
  10810.                         begin
  10811.                             insert into #proctext(procedure_text) values( N'end' )
  10812.                             insert into #proctext(procedure_text) values( N'else' )
  10813.                             insert into #proctext(procedure_text) values( N'begin' )
  10814.                             insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' )
  10815.                             select @update_created = 1
  10816.                         end
  10817.                         select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  10818.                         select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  10819.  
  10820.                         insert into #proctext(procedure_text) values (
  10821.                              @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  10822.                              N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + 
  10823.                              N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' )
  10824.  
  10825.                         select @spacer = ',' 
  10826.                     end
  10827.                 end
  10828.                 select @art_col = @art_col + 1
  10829.             end
  10830.             FETCH hCColid INTO @this_col
  10831.         end
  10832.         CLOSE hCColid
  10833.         DEALLOCATE hCColid
  10834.  
  10835.         if @update_created = 1
  10836.         begin
  10837.             exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  10838.             if @allow_queued_tran <> 1
  10839.                 exec dbo.sp_MSscript_missing_row_check
  10840.         end
  10841.     end
  10842.  
  10843.     insert into #proctext(procedure_text) values( N'end' )
  10844.     select procedure_text from #proctext order by c1 asc
  10845. end
  10846. go
  10847. EXEC dbo.sp_MS_marksystemobject sp_scriptmappedupdproc
  10848. GO
  10849. grant exec on dbo.sp_scriptmappedupdproc to public
  10850. go
  10851.  
  10852. --------------------------------------------------------------------------------
  10853. --. sp_scriptdynamicupdproc
  10854. --------------------------------------------------------------------------------
  10855.  
  10856. if exists (select * from sysobjects
  10857.     where type = 'P' and name = 'sp_scriptdynamicupdproc')
  10858. drop procedure sp_scriptdynamicupdproc
  10859. go
  10860. raiserror('Creating procedure sp_scriptdynamicupdproc', 0,1)
  10861. go
  10862. create procedure sp_scriptdynamicupdproc 
  10863. (
  10864.     @artid int
  10865. )
  10866. as
  10867.     begin
  10868.     declare @retcode int
  10869.     declare @cmd          nvarchar(4000)
  10870.     declare @dest_owner   nvarchar(255)
  10871.     declare @dest_tabname sysname
  10872.     declare @src_objid    int
  10873.     declare @artcolumns   binary(32)
  10874.     declare @pkcolumns    binary(32)
  10875.     declare @upd_cmd      nvarchar(255)
  10876.     declare @dest_proc    sysname
  10877.     declare @art_cols     int
  10878.     declare @this_col     int
  10879.     declare @art_col      int
  10880.     declare @pk_col       int
  10881.     declare @pkart_col    int
  10882.     declare @isset        int
  10883.     declare @ispk         int
  10884.     declare @isidentity   bit
  10885.     declare @iscomputed   bit
  10886.     declare @bytestr      nvarchar(10)
  10887.     declare @bitstr       nvarchar(10)
  10888.     declare @typestring   nvarchar(255)
  10889.     declare @spacer_param nvarchar(10)
  10890.     declare @update_created  bit
  10891.     declare @pkcomputed   int
  10892.     declare @pubid        int, @allow_queued_tran bit
  10893.  
  10894.     set nocount on 
  10895.  
  10896.     --
  10897.     -- security check
  10898.     --
  10899.     exec @retcode = dbo.sp_MSreplcheck_publish
  10900.     if @@error <> 0 or @retcode <> 0
  10901.     begin
  10902.         return (1)
  10903.     end
  10904.     select @update_created     = 0
  10905.  
  10906.     if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  10907.     begin
  10908.         raiserror (14155, 16, 1 )
  10909.         return 1
  10910.     end
  10911.  
  10912.     -------- create temp table for command fragments
  10913.  
  10914.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  10915.     create table #proctext_params ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  10916.     create table #proctext_paramdef ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  10917.     create table #proctext_pkparams ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  10918.  
  10919.  
  10920.  
  10921.     -------- get sysarticles information
  10922.  
  10923.     select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  10924.            @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd,
  10925.            @pubid = pubid
  10926.     from sysarticles
  10927.     where artid = @artid
  10928.  
  10929.     if @dest_owner is not null
  10930.     begin
  10931.         select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  10932.     end
  10933.     else
  10934.     begin
  10935.         select @dest_owner = N''
  10936.     end
  10937.  
  10938.     -------- get dest proc name
  10939.  
  10940.     if( 1 != charindex( N'MCALL', upper(@upd_cmd) ) ) or @upd_cmd is null
  10941.     begin
  10942.         raiserror (14156, 16, 1 )
  10943.         return 1
  10944.     end
  10945.  
  10946.     select @allow_queued_tran = allow_queued_tran from syspublications where pubid = @pubid 
  10947.  
  10948.     declare @keep_identity bit
  10949.     if @allow_queued_tran = 1 and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  10950.         select @keep_identity = 1
  10951.     else
  10952.         select @keep_identity = 0
  10953.  
  10954.     select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 )
  10955.     select @cmd = N'if exists (select * from sysobjects where type = ''P''  and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  10956.     insert into #proctext(procedure_text) values( @cmd )
  10957.     insert into #proctext(procedure_text) values( N'go' )
  10958.     insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ' )
  10959.       
  10960.  
  10961.     -------- construct parameter list
  10962.  
  10963.     exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  10964.  
  10965.     exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, @pkcolumns
  10966.  
  10967.     ----- add changed data bitmap
  10968.  
  10969.     select @art_col = 1
  10970.     select @pk_col = 1
  10971.  
  10972.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  10973.     select colid from syscolumns where id = @src_objid order by colid asc
  10974.  
  10975.     OPEN hCColid
  10976.  
  10977.     FETCH hCColid INTO @this_col
  10978.  
  10979.     WHILE (@@fetch_status <> -1)
  10980.     begin
  10981.        exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  10982.        if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  10983.        begin
  10984.             select @art_col = @art_col + 1
  10985.        end
  10986.        FETCH hCColid INTO @this_col
  10987.     end
  10988.     CLOSE hCColid
  10989.     DEALLOCATE hCColid
  10990.  
  10991.     -- Note that bitmap size is based on number of article columns
  10992.     -- (computed by loop above) not source table columns
  10993.  
  10994.     select @cmd = N',@bitmap binary(' + convert(nvarchar,1+(@art_col-1) / 8) + N')'
  10995.  
  10996.     insert into #proctext(procedure_text) values( @cmd )
  10997.     insert into #proctext(procedure_text) values( N'as' )
  10998.  
  10999.  
  11000.  
  11001.     -- Find out if pk is identity
  11002.     declare @pk_is_identity bit
  11003.     select @pk_is_identity = 0
  11004.  
  11005.     exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  11006.  
  11007.     if @artcolumns != @pkcolumns and @pkcomputed = 0
  11008.     begin
  11009.         select @art_col = 1
  11010.  
  11011.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  11012.         select colid from syscolumns where id = @src_objid order by colid asc
  11013.  
  11014.         OPEN hCColid
  11015.  
  11016.         FETCH hCColid INTO @this_col
  11017.  
  11018.         select @pk_is_identity = 1
  11019.  
  11020.         WHILE (@@fetch_status <> -1)
  11021.         begin
  11022.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  11023.             if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  11024.             begin 
  11025.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  11026.                 if @isset != 0
  11027.                 begin
  11028.                     if not (@keep_identity = 1 and 
  11029.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  11030.                     begin
  11031.                         select @pk_is_identity = 0
  11032.                     end
  11033.                 end
  11034.                 select @art_col = @art_col + 1
  11035.             end
  11036.             FETCH hCColid INTO @this_col
  11037.         end
  11038.         CLOSE hCColid
  11039.         DEALLOCATE hCColid
  11040.     end 
  11041.  
  11042.     -- construct UPDATE that does not set PK cols
  11043.     -- only do this if the article contains columns that are not included
  11044.     -- in the pk
  11045.     -- Note: we assume pk columns never change. pk changes will be replicated
  11046.     -- as delete insert.
  11047.  
  11048.     if @artcolumns != @pkcolumns  and @pkcomputed = 0 and @pk_is_identity = 0
  11049.     begin
  11050.  
  11051.         -- create SET clause consisting of CASE statements
  11052.  
  11053.         select @art_col = 1
  11054.         select @spacer_param = N''
  11055.  
  11056.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  11057.         select colid from syscolumns where id = @src_objid order by colid asc
  11058.  
  11059.         OPEN hCColid
  11060.  
  11061.         FETCH hCColid INTO @this_col
  11062.  
  11063.         WHILE (@@fetch_status <> -1)
  11064.         begin
  11065.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  11066.             if @isset != 0  
  11067.             begin
  11068.                 exec @ispk = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  11069.                 
  11070.                 if EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  11071.                     select @iscomputed = 0
  11072.                 else
  11073.                     select @iscomputed = 1
  11074.                 
  11075.                 if (@keep_identity = 1 and 
  11076.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)  
  11077.                     select @isidentity = 1
  11078.                 else
  11079.                     select @isidentity = 0
  11080.                     
  11081.                 -- If not pk, not computed and not identity    
  11082.                 if @ispk = 0 and @iscomputed = 0 and @isidentity = 0
  11083.                 begin
  11084.                     if (@update_created = 0)
  11085.                     begin
  11086.                         insert into #proctext(procedure_text) values( 
  11087.                             N'declare @stmt nvarchar(4000), @spacer nvarchar(1)')
  11088.  
  11089.                         insert into #proctext(procedure_text) values( 
  11090.                             N'select @spacer =N''''')
  11091.  
  11092.                         insert into #proctext(procedure_text) values( 
  11093.                             N'select @stmt = N''update ' + 
  11094.                             replace(@dest_owner + QUOTENAME(@dest_tabname), N'''', N'''''' ) +
  11095.                             N' set ''')
  11096.  
  11097.                         select @update_created = 1
  11098.                     end
  11099.  
  11100.                     select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  11101.                     select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  11102.  
  11103.                     insert into #proctext(procedure_text) values (
  11104.                          N'if substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  11105.                          N' = ' + @bitstr)
  11106.  
  11107.                     insert into #proctext(procedure_text) values (N'begin')
  11108.  
  11109.                     -- Append statement
  11110.                     insert into #proctext(procedure_text) values (
  11111.                          N'select @stmt = @stmt + @spacer + ' + 
  11112.                          N'N''' + replace(QUOTENAME(col_name( @src_objid, @this_col)), N'''', N'''''') + N''' + ' +
  11113.                          N'N''=@'+ convert( nvarchar, @art_col ) + N'''')
  11114.  
  11115.                     -- Set @spacer is the proc
  11116.                     insert into #proctext(procedure_text) values (
  11117.                         N'select @spacer = N'',''')
  11118.  
  11119.                     insert into #proctext(procedure_text) values (N'end')
  11120.                 end
  11121.                 -- If pk or (not computed and not identity) add the param
  11122.                 if @ispk <> 0 or (@iscomputed = 0 and @isidentity = 0)
  11123.                 begin
  11124.                     -- Add to param list
  11125.                     if (@ispk <> 0)
  11126.                       begin
  11127.                         -- Use primary key value
  11128.                         insert into #proctext_params(procedure_text) values( 
  11129.                             @spacer_param + N'@pkc' + convert( nvarchar, @pk_col ))
  11130.  
  11131.                         -- Increment primary key counter
  11132.                         select @pk_col = @pk_col + 1;
  11133.  
  11134.                       end
  11135.                     else
  11136.                         -- Use column value
  11137.                         insert into #proctext_params(procedure_text) values( 
  11138.                             @spacer_param + N'@c' + convert( nvarchar, @art_col ))
  11139.  
  11140.                     -- Get type str
  11141.                     exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  11142.  
  11143.                     -- Append typedef
  11144.                     insert into #proctext_paramdef(procedure_text) values (
  11145.                          @spacer_param + N'@' + convert( nvarchar, @art_col ) + 
  11146.                          N' ' + @typestring )
  11147.  
  11148.                     select @spacer_param = ',' 
  11149.                 end
  11150.  
  11151.                 select @art_col = @art_col + 1
  11152.             end
  11153.                FETCH hCColid INTO @this_col
  11154.         end
  11155.         CLOSE hCColid
  11156.         DEALLOCATE hCColid
  11157.  
  11158.         if @update_created = 1
  11159.         begin
  11160.  
  11161.             -- Append statement of the start of where clause
  11162.             insert into #proctext(procedure_text) values (
  11163.                  N'    select @stmt = @stmt + N'' ')
  11164.  
  11165.             -- Escape ' in the where clause
  11166.             declare @low_mark int, @high_mark int
  11167.             select @low_mark = max(c1) from #proctext
  11168.             -- Pass in @artcolumns so that the where clause will use the ordinal in the
  11169.             -- article bit map rather then one in pk bitmap. This is consistent with
  11170.             -- the type def string.
  11171.             -- UNDONE: change comments in sp_scriptpkwhereclause
  11172.             -- Use prefix '@' to be consistent with type def string
  11173.             exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, '@', @artcolumns
  11174.             select @high_mark = max(c1) from #proctext
  11175.             update #proctext set procedure_text = replace ( procedure_text, N'''', N'''''') 
  11176.                 where c1 > @low_mark and c1 <= @high_mark
  11177.  
  11178.             -- Close the where clause
  11179.             insert into #proctext(procedure_text) values (
  11180.                  N'''')
  11181.  
  11182.             -- Add call to sql_executesql and the param list
  11183.             insert into #proctext(procedure_text) values( 
  11184.                 N'exec sp_executesql @stmt, N'' ')
  11185.  
  11186.             -- Add param def
  11187.             insert into #proctext(procedure_text) 
  11188.                 select procedure_text from #proctext_paramdef order by c1 asc
  11189.  
  11190.             -- Close the param def
  11191.             insert into #proctext(procedure_text) values (
  11192.                  N''',')
  11193.  
  11194.             -- Add param list
  11195.             insert into #proctext(procedure_text) 
  11196.                 select procedure_text from #proctext_params order by c1 asc
  11197.  
  11198.             if @allow_queued_tran <> 1
  11199.                 exec dbo.sp_MSscript_missing_row_check
  11200.         end
  11201.  
  11202.     end
  11203.  
  11204.     select procedure_text from #proctext order by c1 asc
  11205. end
  11206. go
  11207. EXEC dbo.sp_MS_marksystemobject sp_scriptdynamicupdproc
  11208. GO
  11209. grant exec on dbo.sp_scriptdynamicupdproc to public
  11210. go
  11211.  
  11212. --------------------------------------------------------------------------------
  11213. --. sp_scriptxupdproc
  11214. --------------------------------------------------------------------------------
  11215.  
  11216. if exists (select * from sysobjects
  11217.     where type = 'P' and name = 'sp_scriptxupdproc')
  11218. drop procedure sp_scriptxupdproc
  11219. go
  11220. raiserror('Creating procedure sp_scriptxupdproc', 0,1)
  11221. go
  11222. create procedure sp_scriptxupdproc @artid int
  11223. as
  11224. BEGIN
  11225.     declare @cmd          nvarchar(4000),
  11226.                 @dest_owner   nvarchar(255),
  11227.                 @dest_tabname sysname,
  11228.                 @src_objid    int,
  11229.                 @artcolumns   binary(32),
  11230.                 @pkcolumns    binary(32),
  11231.                 @upd_cmd      nvarchar(255),
  11232.                 @dest_proc    sysname,
  11233.                 @this_col     int,
  11234.                 @art_col      int,
  11235.                 --@pkart_col    int,
  11236.                 @isset        int,
  11237.                 @rc int,
  11238.                 @fhasnonpkuniquekeys int,
  11239.                 @pkcomputed   int,
  11240.                 @typestring   nvarchar(255),
  11241.                 @spacer       nvarchar(10),
  11242.                 @pubid          int, 
  11243.                 @param_count  int
  11244.                 ,@queued_check bit, @exists_else bit
  11245.                 ,@qwhere_string nvarchar(4000)
  11246.  
  11247.     set nocount on
  11248.     --
  11249.     -- security check
  11250.     --
  11251.     exec @rc = dbo.sp_MSreplcheck_publish
  11252.     if @@error <> 0 or @rc <> 0
  11253.     begin
  11254.         return (1)
  11255.     end
  11256.  
  11257.     if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  11258.     begin
  11259.         raiserror (14155, 16, 1 )
  11260.         return 1
  11261.     end
  11262.  
  11263.     select @exists_else = 0
  11264.              ,@fhasnonpkuniquekeys = 0
  11265.  
  11266.     -------- create temp table for command fragments
  11267.  
  11268.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  11269.  
  11270.     -------- get sysarticles information
  11271.  
  11272.     select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  11273.            @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd
  11274.     from sysarticles
  11275.     where artid = @artid
  11276.  
  11277.     if @dest_owner is not null
  11278.     begin
  11279.         select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  11280.     end
  11281.     else
  11282.     begin
  11283.         select @dest_owner = N''
  11284.     end
  11285.  
  11286.     -- Check if this is a queued publication
  11287.     select @queued_check = ISNULL(allow_queued_tran, 0) 
  11288.     from syspublications
  11289.     where pubid = @pubid
  11290.  
  11291.     -------- get dest proc name
  11292.  
  11293.     if( 1 != charindex( N'XCALL', upper(@upd_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @upd_cmd is null
  11294.     begin
  11295.         raiserror (14156, 16, 1 )
  11296.         return 1
  11297.     end
  11298.  
  11299.     declare @keep_identity bit
  11300.     if exists (select * from syspublications where pubid = @pubid and
  11301.         allow_queued_tran = 1) and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  11302.         select @keep_identity = 1
  11303.     else
  11304.         select @keep_identity = 0
  11305.  
  11306.     select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 )
  11307.     select @cmd = N'if exists (select * from sysobjects where type = ''P''  and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  11308.     insert into #proctext(procedure_text) values( @cmd )
  11309.     insert into #proctext(procedure_text) values( N'go' )
  11310.     insert into #proctext( procedure_text ) values (  N'create procedure ' + QUOTENAME(@dest_proc) + N' ')
  11311.  
  11312.     -------- construct parameter list
  11313.  
  11314.     exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  11315.  
  11316.     -- Send null as @pkcolumns. We don't need pk parameters.
  11317.     exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, NULL, @param_count output
  11318.  
  11319.     insert into #proctext(procedure_text) values ( N'as' )
  11320.  
  11321.     --
  11322.     -- If we are a part of queued publication 
  11323.     --
  11324.     if (@queued_check = 1)
  11325.     begin
  11326.         --
  11327.         -- Check if we have non PK unique keys
  11328.         --
  11329.         exec @fhasnonpkuniquekeys = dbo.sp_repltablehasnonpkuniquekey @tabid = @src_objid
  11330.         if (@fhasnonpkuniquekeys = 1)
  11331.         begin
  11332.             --
  11333.             -- There are non PK unique keys
  11334.             -- update only if updated values of non PK unique key(s) do not exist
  11335.             --
  11336.             select @cmd = N'
  11337. if not exists (select * from ' + @dest_owner + QUOTENAME(@dest_tabname) + N' '
  11338.             insert into #proctext(procedure_text) values( @cmd )
  11339.             exec @rc = sp_replscriptuniquekeywhereclause @tabid = @src_objid
  11340.                                                             ,@columns = @artcolumns
  11341.                                                             ,@prefix = '@c' 
  11342.                                                             ,@mode = 2
  11343.                                                             ,@paramcount = @param_count
  11344.             if (@@error != 0 or @rc != 0)
  11345.                 return 1
  11346.             select @cmd = N')
  11347. begin'
  11348.             insert into #proctext(procedure_text) values( @cmd )
  11349.         end
  11350.     end
  11351.  
  11352.     -------- now create the update statement
  11353.  
  11354.     -- construct test to see if pk has changed 
  11355.     -- only do this if the article has columns not included in the pk
  11356.  
  11357.     exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  11358.  
  11359.     declare @pk_is_identity bit
  11360.     select @pk_is_identity = 0
  11361.  
  11362.     if @artcolumns != @pkcolumns and @pkcomputed = 0
  11363.     begin
  11364.         select @cmd = N'if'
  11365.  
  11366.         select @art_col = 1
  11367.         --select @pkart_col = 1
  11368.         select @spacer = ' '
  11369.  
  11370.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  11371.         select colid from syscolumns where id = @src_objid order by colid asc
  11372.  
  11373.         OPEN hCColid
  11374.  
  11375.         FETCH hCColid INTO @this_col
  11376.  
  11377.         select @pk_is_identity = 1
  11378.         WHILE (@@fetch_status <> -1)
  11379.         begin
  11380.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  11381.             if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  11382.             begin
  11383.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  11384.                 if @isset != 0
  11385.                 begin
  11386.                     if not (@keep_identity = 1 and 
  11387.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  11388.                     begin
  11389.                         select @pk_is_identity = 0
  11390.                         select @cmd = @cmd + @spacer + N'@c'+convert( nvarchar, @art_col + @param_count/2) + 
  11391.                             N' = @c' + convert( nvarchar, @art_col ) 
  11392.                         select @spacer = N' and '
  11393.                         --select @pkart_col = @pkart_col + 1
  11394.                         if len( @cmd ) > 3000
  11395.                         begin
  11396.                         insert into #proctext(procedure_text) values( @cmd )
  11397.                             select @cmd = N''
  11398.                         end
  11399.                     end
  11400.                 end
  11401.                 select @art_col = @art_col + 1
  11402.             end
  11403.             FETCH hCColid INTO @this_col
  11404.         end
  11405.  
  11406.         CLOSE hCColid
  11407.         DEALLOCATE hCColid
  11408.  
  11409.         if @pk_is_identity = 0
  11410.         begin
  11411.             insert into #proctext(procedure_text) values( @cmd )
  11412.  
  11413.             insert into #proctext(procedure_text) values( N'begin' )
  11414.  
  11415.             -- construct update if pk hasn't changed
  11416.             -- We know that there would be a least one column for the update below, even if
  11417.             -- the columns outside the pk are identity or timestamp. Since identity and timestamp
  11418.             -- will be mapped off unless it is queued tran. In that case, we have 'msrepl_tran_version'
  11419.             select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  11420.  
  11421.             -- create SET clause
  11422.  
  11423.             select @art_col = 1
  11424.             select @spacer = N' '
  11425.  
  11426.             DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  11427.             select colid from syscolumns where id = @src_objid order by colid asc
  11428.  
  11429.             OPEN hCColid
  11430.  
  11431.             FETCH hCColid INTO @this_col
  11432.             WHILE (@@fetch_status <> -1)
  11433.             begin
  11434.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  11435.                 if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  11436.                 begin
  11437.                     exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  11438.                     if @isset = 0
  11439.                     begin
  11440.                         if not (@keep_identity = 1 and 
  11441.                             columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  11442.                         begin
  11443.                             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + 
  11444.                                 N' = @c' + convert( nvarchar, @art_col + @param_count/2) 
  11445.                             select @spacer = N','
  11446.  
  11447.                             if len( @cmd ) > 3000
  11448.                             begin
  11449.                                 insert into #proctext(procedure_text) values( @cmd )
  11450.                                 select @cmd = N''
  11451.                             end
  11452.  
  11453.                             --
  11454.                             -- Queued processing:if this is the row version column : need to add to where clause
  11455.                             --
  11456.                             if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  11457.                                 select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )                        
  11458.                         end
  11459.                     end
  11460.                     select @art_col = @art_col + 1
  11461.                 end
  11462.                 FETCH hCColid INTO @this_col
  11463.             end
  11464.             CLOSE hCColid
  11465.             DEALLOCATE hCColid
  11466.  
  11467.             insert into #proctext(procedure_text) values( @cmd )
  11468.  
  11469.             exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @artcolumns
  11470.             if (@queued_check = 1)
  11471.                 insert into #proctext(procedure_text) values( @qwhere_string )
  11472.             else
  11473.                 exec dbo.sp_MSscript_missing_row_check
  11474.  
  11475.             insert into #proctext(procedure_text) values( N'end' )
  11476.             insert into #proctext(procedure_text) values( N'else' )
  11477.             insert into #proctext(procedure_text) values( N'begin' )
  11478.  
  11479.             select @exists_else = 1
  11480.  
  11481.         end
  11482.     end -- end if artcols != pkcols
  11483.  
  11484.     --
  11485.     -- If we are a part of queued publication then 
  11486.     -- update only if updated value of PK does not exist
  11487.     --
  11488.     if (@queued_check = 1 and @pk_is_identity = 0)
  11489.     begin
  11490.         select @cmd = N'
  11491. if not exists (select * from ' + @dest_owner + QUOTENAME(@dest_tabname) + N' '
  11492.         insert into #proctext(procedure_text) values( @cmd )
  11493.         exec @rc = sp_replscriptuniquekeywhereclause @tabid = @src_objid
  11494.                                                             ,@columns = @artcolumns
  11495.                                                             ,@prefix = '@c' 
  11496.                                                             ,@mode = 3
  11497.                                                             ,@paramcount = @param_count
  11498.         if (@@error != 0 or @rc != 0)
  11499.             return 1
  11500.         select @cmd = N')
  11501. begin'
  11502.         insert into #proctext(procedure_text) values( @cmd )
  11503.     end
  11504.  
  11505.     -- construct update if pk has changed
  11506.     select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  11507.  
  11508.     -- create SET clause
  11509.  
  11510.     select @art_col = 1
  11511.     select @spacer = N' '
  11512.  
  11513.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  11514.     select colid from syscolumns where id = @src_objid order by colid asc
  11515.  
  11516.     OPEN hCColid
  11517.  
  11518.     FETCH hCColid INTO @this_col
  11519.     WHILE (@@fetch_status <> -1)
  11520.     begin
  11521.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  11522.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  11523.         begin
  11524.             if not (@keep_identity = 1 and 
  11525.                 columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  11526.             begin
  11527.                 select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + 
  11528.                     N' = @c' + convert( nvarchar, @art_col + @param_count/2 ) 
  11529.                 select @spacer = N','
  11530.  
  11531.                 if len( @cmd ) > 3000
  11532.                 begin
  11533.                 insert into #proctext(procedure_text) values( @cmd )
  11534.                     select @cmd = N''
  11535.                 end
  11536.  
  11537.                 --
  11538.                 -- Queued processing:if this is the row version column : need to add to where clause
  11539.                 --
  11540.                 if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  11541.                     select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )                        
  11542.             end
  11543.             select @art_col = @art_col + 1
  11544.         end
  11545.         FETCH hCColid INTO @this_col
  11546.     end
  11547.  
  11548.     CLOSE hCColid
  11549.     DEALLOCATE hCColid
  11550.  
  11551.     insert into #proctext(procedure_text) values( @cmd )
  11552.  
  11553.     exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @artcolumns
  11554.     if (@queued_check = 1)
  11555.     begin
  11556.         insert into #proctext(procedure_text) values( @qwhere_string ) 
  11557.         if (@pk_is_identity = 0)
  11558.         begin
  11559.             select @cmd = N'
  11560. end'
  11561.             insert into #proctext(procedure_text) values( @cmd )
  11562.         end
  11563.     end
  11564.     else
  11565.         exec dbo.sp_MSscript_missing_row_check
  11566.  
  11567.     if @exists_else = 1
  11568.         insert into #proctext(procedure_text) values( N'end' )
  11569.  
  11570.     --
  11571.     -- End the if exists block for Queued publications
  11572.     --
  11573.     if (@queued_check = 1) and (@fhasnonpkuniquekeys = 1)
  11574.     begin
  11575.         select @cmd = N'
  11576. end'
  11577.         insert into #proctext(procedure_text) values( @cmd )
  11578.     end
  11579.  
  11580.     -- flush to client
  11581.  
  11582.     select procedure_text from #proctext order by c1 asc
  11583. END
  11584. go
  11585. EXEC dbo.sp_MS_marksystemobject sp_scriptxupdproc
  11586. GO
  11587. grant exec on dbo.sp_scriptxupdproc to public
  11588. go
  11589.  
  11590. --------------------------------------------------------------------------------
  11591. --. sp_MSgetarticlereinitvalue
  11592. --------------------------------------------------------------------------------
  11593.  
  11594. if exists (select * from sysobjects
  11595.     where type = 'P' and name = 'sp_MSgetarticlereinitvalue')
  11596. drop procedure sp_MSgetarticlereinitvalue
  11597. go
  11598. raiserror('Creating procedure sp_MSgetarticlereinitvalue', 0,1)
  11599. go
  11600. create procedure sp_MSgetarticlereinitvalue (
  11601.     @subscriber             sysname,
  11602.     @subscriberdb         sysname,
  11603.     @artid                 int, 
  11604.     @reinit                 int output
  11605. )
  11606. as
  11607. begin
  11608.     set NOCOUNT ON
  11609.     declare @orig_srvid int
  11610.         ,@retcode int
  11611.         ,@publication sysname
  11612.  
  11613.     --
  11614.     -- PAL security check
  11615.     -- Get publication name using artid
  11616.     --
  11617.     select @publication = p.name
  11618.     from syspublications p join sysarticles a on p.pubid = a.pubid
  11619.     where a.artid = @artid
  11620.     if (@publication is null)
  11621.     begin
  11622.         return 1
  11623.     end
  11624.     exec @retcode = dbo.sp_MSreplcheck_pull @publication = @publication
  11625.     if @@error <> 0 or @retcode <> 0
  11626.     begin
  11627.         return (1)
  11628.     end
  11629.     --
  11630.     -- get the value of reinit flag
  11631.     --
  11632.     select @orig_srvid = srvid from master.dbo.sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  11633.     select @reinit = queued_reinit 
  11634.     from syssubscriptions 
  11635.     where 
  11636.         artid = @artid 
  11637.         and srvid = @orig_srvid
  11638.         and dest_db = @subscriberdb
  11639.  
  11640.     -- All done
  11641.     return 0
  11642. end
  11643. go
  11644. exec dbo.sp_MS_marksystemobject sp_MSgetarticlereinitvalue
  11645. go
  11646. grant execute on dbo.sp_MSgetarticlereinitvalue to public
  11647. go
  11648.  
  11649. --------------------------------------------------------------------------------
  11650. --.    sp_MScomputearticlescreationorder
  11651. --------------------------------------------------------------------------------
  11652. if exists (select * from sysobjects
  11653.     where type = 'P' and name = 'sp_MScomputearticlescreationorder')
  11654. drop procedure sp_MScomputearticlescreationorder
  11655. go
  11656. print ''
  11657. print 'Creating procedure sp_MScomputearticlescreationorder'
  11658. go
  11659. CREATE PROCEDURE sp_MScomputearticlescreationorder
  11660.     @publication sysname
  11661. AS
  11662.     SET NOCOUNT ON
  11663.     DECLARE @pubid int 
  11664.     DECLARE @max_level int
  11665.     DECLARE @current_level int
  11666.     DECLARE @update_level int
  11667.     DECLARE @limit int
  11668.     DECLARE @result int
  11669.     DECLARE @retcode int
  11670.  
  11671.     SELECT @retcode = 0
  11672.  
  11673.     EXEC @retcode = sp_MSreplcheck_publish
  11674.     IF @@ERROR <> 0 OR @retcode <> 0
  11675.         return (1)
  11676.  
  11677.     SELECT @pubid = NULL
  11678.     -- Get the pubid from syspublications 
  11679.     SELECT @pubid = pubid 
  11680.       FROM syspublications
  11681.      WHERE name = @publication
  11682.  
  11683.     IF @@ERROR <> 0
  11684.         RETURN (1)
  11685.  
  11686.     IF @pubid IS NULL
  11687.     BEGIN
  11688.         RAISERROR(20026, 16, -1, @publication)
  11689.         RETURN (1)
  11690.     END
  11691.  
  11692.     EXEC @result = sp_getapplock @Resource = @publication, 
  11693.                 @LockMode = N'Shared', 
  11694.                 @LockOwner = N'Session', 
  11695.                 @LockTimeout = 0
  11696.  
  11697.     IF @result < 0
  11698.     BEGIN
  11699.         RAISERROR(21385, 16, -1, @publication)
  11700.         RETURN (1)
  11701.     END
  11702.  
  11703.     -- Find out the total number of articles in this publication and
  11704.     -- compute the maximum tree height based on the number of articles in 
  11705.     -- the publication. Here, the tree height is counted from the
  11706.     -- leaf-nodes towards the root(s)
  11707.     SELECT @max_level = COUNT(*) + 10,
  11708.            @limit =2 *  COUNT(*) + 11 
  11709.       FROM sysextendedarticlesview 
  11710.      WHERE pubid = @pubid
  11711.  
  11712.     IF @@ERROR <> 0
  11713.     BEGIN
  11714.         RETURN (1)
  11715.     END
  11716.    
  11717.     -- The following temp table contains the minimal amount of 
  11718.     -- article information that we want to keep around and the current
  11719.     -- computed tree level of the article
  11720.     CREATE TABLE #article_level_info
  11721.     (
  11722.         article         sysname collate database_default not null,
  11723.         source_objid    INT     NOT NULL,
  11724.         tree_level      INT     NOT NULL,
  11725.         ref_level       INT     NOT NULL,
  11726.         major_type      TINYINT NOT NULL  -- 1-view&func, 0-other 
  11727.     )  
  11728.    
  11729.     CREATE CLUSTERED INDEX ucarticle_level_info 
  11730.         ON #article_level_info(source_objid)
  11731.  
  11732.     IF @@ERROR <> 0
  11733.     BEGIN
  11734.         GOTO Failure
  11735.     END
  11736.  
  11737.     -- Populate the article level info table. All articles will be
  11738.     -- assigned 0 as their initial tree level. Having 
  11739.     -- a tree level of 0 means that the algorithm hasn't discovered 
  11740.     -- any objects that the article depends on within the publication.
  11741.  
  11742.     INSERT INTO #article_level_info 
  11743.     SELECT name, objid, 0, 0, 
  11744.         CASE type    
  11745.             WHEN 0x40 THEN 1
  11746.             WHEN 0x80 THEN 1
  11747.             ELSE 0 
  11748.         END
  11749.       FROM sysextendedarticlesview
  11750.      WHERE pubid = @pubid
  11751.       
  11752.     -- To jump-start the algorithm, update the tree_level of 
  11753.     -- all articles with no dependency to @max_level.
  11754.  
  11755.     UPDATE #article_level_info 
  11756.        SET tree_level = @max_level
  11757.      WHERE NOT EXISTS (SELECT * 
  11758.                          FROM sysdepends 
  11759.                         WHERE source_objid = id
  11760.                           and id <> depid)
  11761.     IF @@ERROR <> 0
  11762.         GOTO Failure
  11763.  
  11764.     -- For each increasing tree level starting from @max_level, update the 
  11765.     -- the tree_level of articles depending on objects at the current
  11766.     -- level to current level + 1
  11767.     SELECT @current_level = @max_level
  11768.     WHILE 1 = 1
  11769.     BEGIN
  11770.         SELECT @update_level = @current_level + 1
  11771.  
  11772.         UPDATE #article_level_info
  11773.            SET tree_level = @update_level
  11774.           FROM #article_level_info 
  11775.         INNER JOIN sysdepends d
  11776.             ON #article_level_info.source_objid = d.id 
  11777.         INNER JOIN #article_level_info ali1
  11778.             ON (d.depid = ali1.source_objid       
  11779.                AND ali1.tree_level = @current_level
  11780.                AND d.id <> d.depid)
  11781.     
  11782.         -- Terminate the algorithm if we cannot find any articles 
  11783.         -- depending on articles at the current level     
  11784.         IF @@ROWCOUNT = 0
  11785.             GOTO PHASE1
  11786.  
  11787.         IF @@ERROR <> 0
  11788.             GOTO Failure
  11789.  
  11790.         SELECT @current_level = @current_level + 1
  11791.  
  11792.         -- Although there should not be any circular 
  11793.         -- dependencies among the articles, the following
  11794.         -- check is performed to guarantee that 
  11795.         -- the algorithm will terminate even if there 
  11796.         -- is circular dependency among the articles
  11797.         
  11798.         -- Note that with at least one node per level,
  11799.         -- the current level can never exceed the total 
  11800.         -- number of articles (nodes) unless there is
  11801.         -- circular dependency among the articles.
  11802.         
  11803.         -- @limit is defined to be # of articles + 1
  11804.         -- although @limit = # of articles - 1 will be
  11805.         -- sufficient. This is to make absolutely sure that 
  11806.         -- the algorithm will never terminate too early
  11807.  
  11808.         IF @current_level > @limit
  11809.             GOTO PHASE1
  11810.     END
  11811.  
  11812. PHASE1:
  11813.  
  11814.     -- There may be interdependencies among articles 
  11815.     -- that haven't been included in the previous calculations so
  11816.     -- we compute the proper order among these articles here.
  11817.     SELECT @limit = @max_level - 9
  11818.     SELECT @current_level = 0
  11819.     WHILE 1 = 1
  11820.     BEGIN
  11821.         SELECT @update_level = @current_level + 1
  11822.         
  11823.         UPDATE #article_level_info 
  11824.            SET tree_level = @update_level
  11825.           FROM #article_level_info
  11826.         INNER JOIN sysdepends d
  11827.             ON (#article_level_info.source_objid = d.id
  11828.                 AND #article_level_info.tree_level < @max_level) 
  11829.         INNER JOIN #article_level_info ali1
  11830.             ON (d.depid = ali1.source_objid
  11831.                 AND ali1.tree_level = @current_level
  11832.                 AND d.id <> d.depid)
  11833.         IF @@ROWCOUNT = 0
  11834.             GOTO PHASE2
  11835.         
  11836.         IF @@ERROR <> 0
  11837.             GOTO Failure
  11838.  
  11839.         SELECT @current_level = @current_level + 1
  11840.         IF @current_level > @limit
  11841.             GOTO PHASE2
  11842.     END         
  11843.  
  11844. PHASE2:
  11845.  
  11846.     -- Since transactional doesn't keep the nickname around in 
  11847.     -- sysmergearticles as merge does, we need to compute FK/PK ordering on 
  11848.     -- the fly. 
  11849.     SELECT @current_level = 0
  11850.     SELECT @limit = @max_level - 9
  11851.     WHILE 1 = 1
  11852.     BEGIN
  11853.         SELECT @update_level = @current_level + 1
  11854.         
  11855.         UPDATE #article_level_info
  11856.            SET ref_level = @update_level
  11857.           FROM #article_level_info
  11858.         INNER JOIN sysreferences r
  11859.             ON (#article_level_info.source_objid = r.fkeyid
  11860.                 and r.rkeyid <> r.fkeyid)
  11861.         INNER JOIN #article_level_info ali1
  11862.             ON (r.rkeyid = ali1.source_objid 
  11863.                 AND ali1.ref_level = @current_level)
  11864.         IF @@ROWCOUNT = 0
  11865.             GOTO PHASE3
  11866.  
  11867.         IF @@ERROR <> 0
  11868.             GOTO Failure
  11869.  
  11870.         SELECT @current_level = @current_level + 1
  11871.         IF @current_level > @limit
  11872.             GOTO PHASE3
  11873.     END
  11874.  
  11875. PHASE3:
  11876.  
  11877.     -- Select the articles out of #article_level_info 
  11878.     -- in ascending order of tree_level. This will give
  11879.     -- the proper order in which articles can be created
  11880.     -- without violating the internal dependencies among
  11881.     -- themselves. Note that this algorithm still allows 
  11882.     -- unresolved external references outside the publication.
  11883.     -- All this algorithm can guarantee is that all articles will
  11884.     -- be created successfully using the resulting order if 
  11885.     -- there is no dependent object outside the publication. 
  11886.     -- We need to order the articles in reverse ref_level
  11887.     -- to account for FK/PK constraints when dropping/deleting rows/truncating
  11888.     -- tables on the Subscriber.
  11889.  
  11890.     SELECT article
  11891.       FROM #article_level_info
  11892.     ORDER BY major_type ASC, tree_level ASC, ref_level DESC
  11893.  
  11894.     DROP TABLE #article_level_info
  11895.     RETURN (0)
  11896.  
  11897. Failure:
  11898.  
  11899.     DROP TABLE #article_level_info
  11900.     RETURN (1)
  11901. GO
  11902.  
  11903. exec dbo.sp_MS_marksystemobject sp_MScomputearticlescreationorder
  11904. go
  11905. grant execute on sp_MScomputearticlescreationorder to public
  11906. go
  11907.  
  11908. --------------------------------------------------------------------------------
  11909. --.    sp_MSscriptmvastablenci
  11910. --------------------------------------------------------------------------------
  11911. if exists (select * from sysobjects
  11912.     where type = 'P' and name = 'sp_MSscriptmvastablenci')
  11913. drop procedure sp_MSscriptmvastablenci
  11914. go
  11915. print ''
  11916. print 'Creating procedure sp_MSscriptmvastablenci'
  11917. go
  11918.  
  11919. create procedure sp_MSscriptmvastablenci @artid int
  11920. as
  11921. declare @cmd          nvarchar(4000)
  11922. declare @dest_owner   nvarchar(255)
  11923. declare @dest_tabname sysname
  11924. declare @src_objid    int
  11925. declare @constraint_name  sysname
  11926. declare @spacer          nvarchar(1)
  11927. declare @srcobj          nvarchar(1000)
  11928. declare @colname      sysname
  11929. declare @indkey          int
  11930. declare @indid          int
  11931. declare @status          int
  11932. declare @unique          nvarchar(10)
  11933. declare @cmd_sep      nvarchar(10)
  11934.  
  11935.  
  11936. -------- security check, db_owner
  11937. declare @retcode int
  11938. exec @retcode = dbo.sp_MSreplcheck_publish
  11939. if @@ERROR <> 0 or @retcode <> 0
  11940.     return(1)
  11941.  
  11942. -------- create temp table for command fragments
  11943.  
  11944. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  11945.  
  11946. -------- get sysarticles information
  11947.  
  11948. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  11949.        @src_objid = objid
  11950. from sysarticles
  11951. where artid = @artid
  11952.  
  11953. if @dest_owner is not null
  11954. begin
  11955.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  11956. end
  11957. else
  11958. begin
  11959.     select @dest_owner = N''
  11960. end
  11961.  
  11962. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  11963. select @cmd_sep = N''
  11964.  
  11965. DECLARE hCIdx CURSOR LOCAL FAST_FORWARD FOR
  11966. select name, indid, status from sysindexes where id = @src_objid and indid > 1 order by indid asc
  11967.  
  11968. OPEN hCIdx
  11969. FETCH hCIdx INTO @constraint_name, @indid, @status
  11970.  
  11971. WHILE (@@fetch_status <> -1)
  11972. begin
  11973.     if @status & 2 = 2
  11974.     begin
  11975.         select @unique = N' unique '
  11976.     end
  11977.     else
  11978.     begin
  11979.         select @unique = N' '
  11980.     end
  11981.  
  11982.     insert into #proctext(procedure_text) values( @cmd_sep )
  11983.     select @cmd_sep = N'GO'
  11984.  
  11985.     select @cmd = N'create' + @unique + N'nonclustered index ' + QUOTENAME(@constraint_name) + N' on ' +@dest_owner + QUOTENAME(@dest_tabname) + N'('
  11986.     insert into #proctext(procedure_text) values( @cmd )
  11987.  
  11988.     select @spacer = N' '
  11989.     select @cmd = N''
  11990.  
  11991.     select @indkey = 1
  11992.     while (@indkey <= 16)
  11993.     begin    
  11994.         select @colname = index_col(@srcobj, @indid, @indkey)
  11995.         if (@colname is null)
  11996.         begin
  11997.             select @indkey = 16
  11998.         end
  11999.         else
  12000.         begin
  12001.             select @cmd = @cmd + @spacer + QUOTENAME(@colname)
  12002.             select @spacer = N','
  12003.  
  12004.             if len( @cmd ) > 3000
  12005.             begin
  12006.                 insert into #proctext(procedure_text) values( @cmd )
  12007.                 select @cmd = N''
  12008.             end
  12009.         end
  12010.         select @indkey = @indkey + 1
  12011.     end
  12012.  
  12013.     insert into #proctext(procedure_text) values( @cmd )
  12014.     insert into #proctext(procedure_text) values( N')' )
  12015.     
  12016.     FETCH hCIdx INTO @constraint_name, @indid, @status
  12017. end
  12018.  
  12019. CLOSE hCIdx
  12020. DEALLOCATE hCIdx
  12021. select procedure_text from #proctext order by c1 asc
  12022.  
  12023. go
  12024. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastablenci
  12025. GO
  12026. grant exec on dbo.sp_MSscriptmvastablenci to public
  12027. go
  12028. --------------------------------------------------------------------------------
  12029. --. sp_MSscriptmvastablepkc
  12030. --------------------------------------------------------------------------------
  12031. if exists (select * from sysobjects
  12032.     where type = 'P' and name = 'sp_MSscriptmvastablepkc')
  12033. drop procedure sp_MSscriptmvastablepkc
  12034. go
  12035. print ''
  12036. print 'Creating procedure sp_MSscriptmvastablepkc'
  12037. go
  12038.  
  12039. create procedure sp_MSscriptmvastablepkc @artid int
  12040. as
  12041. declare @cmd          nvarchar(4000)
  12042. declare @dest_owner   nvarchar(255)
  12043. declare @dest_tabname sysname
  12044. declare @src_objid    int
  12045. declare @constraint_name  sysname
  12046. declare @spacer          nvarchar(1)
  12047. declare @srcobj          nvarchar(1000)
  12048. declare @colname      sysname
  12049. declare @indkey          int
  12050. declare @indid          int
  12051.  
  12052. -------- security check, db_owner
  12053. declare @retcode int
  12054. exec @retcode = dbo.sp_MSreplcheck_publish
  12055. if @@ERROR <> 0 or @retcode <> 0
  12056.     return(1)
  12057.  
  12058. -------- create temp table for command fragments
  12059.  
  12060. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  12061.  
  12062. -------- get sysarticles information
  12063.  
  12064. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  12065.        @src_objid = objid
  12066. from sysarticles
  12067. where artid = @artid
  12068.  
  12069. if @dest_owner is not null
  12070. begin
  12071.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  12072. end
  12073. else
  12074. begin
  12075.     select @dest_owner = N''
  12076. end
  12077.  
  12078. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  12079.  
  12080. select @constraint_name = name, @indid = indid from sysindexes where id = @src_objid and status & 16 <> 0
  12081.  
  12082. select @cmd = N'alter table ' + @dest_owner + QUOTENAME(@dest_tabname) collate database_default + N' add constraint ' + QUOTENAME(@constraint_name) collate database_default + N' primary key clustered ('
  12083. insert into #proctext(procedure_text) values( @cmd )
  12084.  
  12085. select @spacer = N' '
  12086. select @cmd = N''
  12087.  
  12088. select @indkey = 1
  12089. while (@indkey <= 16)
  12090. begin    
  12091.     select @colname = index_col(@srcobj, @indid, @indkey)
  12092.     if (@colname is null)
  12093.     begin
  12094.         select @indkey = 16
  12095.     end
  12096.     else
  12097.     begin
  12098.         select @cmd = @cmd + @spacer + QUOTENAME(@colname) collate database_default
  12099.         select @spacer = N','
  12100.  
  12101.         if len( @cmd ) > 3000
  12102.         begin
  12103.             insert into #proctext(procedure_text) values( @cmd )
  12104.             select @cmd = N''
  12105.         end
  12106.     end
  12107.     select @indkey = @indkey + 1
  12108. end
  12109.  
  12110. insert into #proctext(procedure_text) values( @cmd )
  12111.  
  12112. insert into #proctext(procedure_text) values( N')' )
  12113.  
  12114. select procedure_text from #proctext order by c1 asc
  12115.  
  12116. go
  12117. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastablepkc
  12118. GO
  12119. grant exec on dbo.sp_MSscriptmvastablepkc to public
  12120. go
  12121. --------------------------------------------------------------------------------
  12122. --. sp_MSscriptmvastableidx
  12123. --------------------------------------------------------------------------------
  12124. if exists (select * from sysobjects
  12125.     where type = 'P' and name = 'sp_MSscriptmvastableidx')
  12126. drop procedure sp_MSscriptmvastableidx
  12127. go
  12128. print ''
  12129. print 'Creating procedure sp_MSscriptmvastableidx'
  12130. go
  12131.  
  12132. create procedure sp_MSscriptmvastableidx @artid int
  12133. as
  12134. declare @cmd          nvarchar(4000)
  12135. declare @dest_owner   nvarchar(255)
  12136. declare @dest_tabname sysname
  12137. declare @src_objid    int
  12138. declare @constraint_name  sysname
  12139. declare @spacer          nvarchar(1)
  12140. declare @srcobj          nvarchar(1000)
  12141. declare @colname      sysname
  12142. declare @indkey          int
  12143. declare @indid          int
  12144.  
  12145. -------- security check, db_owner
  12146. declare @retcode int
  12147. exec @retcode = dbo.sp_MSreplcheck_publish
  12148. if @@ERROR <> 0 or @retcode <> 0
  12149.     return(1)
  12150.  
  12151. -------- create temp table for command fragments
  12152.  
  12153. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  12154.  
  12155. -------- get sysarticles information
  12156.  
  12157. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  12158.        @src_objid = objid
  12159. from sysarticles
  12160. where artid = @artid
  12161.  
  12162. if @dest_owner is not null
  12163. begin
  12164.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  12165. end
  12166. else
  12167. begin
  12168.     select @dest_owner = N''
  12169. end
  12170.  
  12171. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  12172.  
  12173. select @constraint_name = name, @indid = indid from sysindexes where id = @src_objid and status & 16 <> 0
  12174.  
  12175. select @cmd = N'create unique clustered index ' + QUOTENAME(@constraint_name) + N' on ' +@dest_owner + QUOTENAME(@dest_tabname) + N'('
  12176. insert into #proctext(procedure_text) values( @cmd )
  12177.  
  12178. select @spacer = N' '
  12179. select @cmd = N''
  12180.  
  12181. select @indkey = 1
  12182. while (@indkey <= 16)
  12183. begin    
  12184.     select @colname = index_col(@srcobj, @indid, @indkey)
  12185.     if (@colname is null)
  12186.     begin
  12187.         select @indkey = 16
  12188.     end
  12189.     else
  12190.     begin
  12191.         select @cmd = @cmd + @spacer + QUOTENAME(@colname)
  12192.         select @spacer = N','
  12193.  
  12194.         if len( @cmd ) > 3000
  12195.         begin
  12196.             insert into #proctext(procedure_text) values( @cmd )
  12197.             select @cmd = N''
  12198.         end
  12199.     end
  12200.     select @indkey = @indkey + 1
  12201. end
  12202.  
  12203. insert into #proctext(procedure_text) values( @cmd )
  12204.  
  12205. insert into #proctext(procedure_text) values( N')' )
  12206.  
  12207. select procedure_text from #proctext order by c1 asc
  12208.  
  12209. go
  12210. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastableidx
  12211. GO
  12212. grant exec on dbo.sp_MSscriptmvastableidx to public
  12213. go
  12214. --------------------------------------------------------------------------------
  12215. --. sp_MSscriptmvastable
  12216. --------------------------------------------------------------------------------
  12217. if exists (select * from sysobjects
  12218.     where type = 'P' and name = 'sp_MSscriptmvastable')
  12219. drop procedure sp_MSscriptmvastable
  12220. go
  12221. print ''
  12222. print 'Creating procedure sp_MSscriptmvastable'
  12223. go
  12224.  
  12225. create procedure sp_MSscriptmvastable @artid int
  12226. as
  12227. declare @cmd          nvarchar(4000)
  12228. declare @dest_owner   nvarchar(255)
  12229. declare @dest_tabname sysname
  12230. declare @src_objid    int
  12231. declare @artcolumns   binary(32)
  12232. declare @schema_option binary(8)
  12233. declare @art_col      int
  12234. declare @this_col      int
  12235. declare @isset          int
  12236. declare @use_base_type tinyint
  12237.  
  12238. declare @spacer          nvarchar(1)
  12239. declare @nullability  nvarchar(10)
  12240. declare @typestring   nvarchar(255)
  12241. declare @col_name      sysname
  12242.  
  12243. -------- security check, db_owner
  12244. declare @retcode int
  12245. exec @retcode = dbo.sp_MSreplcheck_publish
  12246. if @@ERROR <> 0 or @retcode <> 0
  12247.     return(1)
  12248.  
  12249. -------- create temp table for command fragments
  12250.  
  12251. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  12252.  
  12253. -------- get sysarticles information
  12254.  
  12255. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  12256.        @src_objid = objid, @artcolumns = columns, 
  12257.        @use_base_type = substring(schema_option,8,1) & 32
  12258. from sysarticles
  12259. where artid = @artid
  12260.  
  12261. if @dest_owner is not null
  12262. begin
  12263.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  12264. end
  12265. else
  12266. begin
  12267.     select @dest_owner = N''
  12268. end
  12269.  
  12270. -- script out CREATE TABLE statement
  12271.  
  12272. -- begin create table
  12273. select @cmd = N'create table ' + @dest_owner + QUOTENAME(@dest_tabname) + N'('
  12274. insert into #proctext(procedure_text) values( @cmd )
  12275.  
  12276. -- columns
  12277. select @art_col = 1
  12278. select @spacer = N' '
  12279.  
  12280. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  12281. select colid from syscolumns where id = @src_objid order by colid asc
  12282.  
  12283. OPEN hCColid
  12284.  
  12285. FETCH hCColid INTO @this_col
  12286.  
  12287. WHILE (@@fetch_status <> -1)
  12288. begin
  12289.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  12290.    select @col_name = name, 
  12291.           @nullability = case isnullable 
  12292.           when 0 then N'NOT NULL' 
  12293.           else N'NULL' end
  12294.           from syscolumns where id=@src_objid and @this_col=colid 
  12295.    if @isset != 0 and @col_name is not null
  12296.    begin
  12297.         if @use_base_type <> 0
  12298.         begin
  12299.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  12300.         end
  12301.         else
  12302.         begin
  12303.             exec dbo.sp_MSgettypestringudt @src_objid, @this_col, @typestring OUTPUT
  12304.         end
  12305.         select @cmd = @spacer + QUOTENAME(@col_name) + N' ' + @typestring + N' ' + @nullability 
  12306.         insert into #proctext(procedure_text) values( @cmd )
  12307.         select @art_col = @art_col + 1
  12308.         select @spacer = N','
  12309.    end
  12310.    FETCH hCColid INTO @this_col
  12311. end
  12312.  
  12313. CLOSE hCColid
  12314. DEALLOCATE hCColid
  12315.  
  12316. -- end create table
  12317. insert into #proctext(procedure_text) values( N')' )
  12318.  
  12319. select procedure_text from #proctext order by c1 asc
  12320. go
  12321. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastable
  12322. GO
  12323. grant exec on dbo.sp_MSscriptmvastable to public
  12324. go
  12325. --------------------------------------------------------------------------------
  12326. --. sp_verify_publication
  12327. --------------------------------------------------------------------------------
  12328. if exists (select * from sysobjects
  12329.     where type = 'P' and name = 'sp_verify_publication')
  12330. revoke execute on sp_verify_publication to public
  12331. go
  12332. --------------------------------------------------------------------------------
  12333. --. sp_MSscript_insert_subwins
  12334. --------------------------------------------------------------------------------
  12335.  
  12336. if exists (select * from sysobjects
  12337.     where type = 'P' and name = 'sp_MSscript_insert_subwins')
  12338. drop procedure sp_MSscript_insert_subwins
  12339. go
  12340. raiserror('Creating procedure sp_MSscript_insert_subwins', 0,1)
  12341. go
  12342. create procedure sp_MSscript_insert_subwins (
  12343.     @publication sysname,
  12344.     @article     sysname, 
  12345.     @objid int,
  12346.     @columns binary(32),
  12347.     @identity_insert bit)
  12348. AS
  12349. BEGIN
  12350.     declare @cmd nvarchar(4000)
  12351.             ,@qualname nvarchar(512)
  12352.             ,@column_string nvarchar(4000)
  12353.             ,@var_string nvarchar(4000)
  12354.             ,@colname      sysname
  12355.             ,@ccoltype     sysname
  12356.             ,@this_col     int
  12357.             ,@rc           int
  12358.             ,@num_col      int
  12359.  
  12360.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  12361.  
  12362.     select @cmd = N'
  12363.     if (@error in (0, 547, 2601, 2627) and @execution_mode = @QSubWins)
  12364.     begin
  12365.         ' + N'--
  12366.         ' + N'-- Subscriber Wins resolution
  12367.         ' + N'--
  12368.         if (@rowcount = 1 and @error = 0)
  12369.         begin'
  12370.  
  12371.     insert into #proctext(procedure_text) values( @cmd )
  12372.  
  12373.     select @cmd = N'
  12374.             ' + N'--
  12375.             ' + N'-- No conflict for this command
  12376.             ' + N'-- do nothing
  12377.             ' + N'-- will remove this code block later 
  12378.             ' + N'-- for optimization
  12379.             ' + N'--
  12380.             select @retcode = 0
  12381.         end'
  12382.  
  12383.     insert into #proctext(procedure_text) values( @cmd )
  12384.  
  12385.     select @cmd = N'        
  12386.         else if (@rowcount = 0 and @error in (547, 2601, 2627))
  12387.         begin
  12388.             ' + N'--
  12389.             ' + N'-- Conflict for this command
  12390.             ' + N'-- Row already exists
  12391.             ' + N'-- delete and insert row with Queue values
  12392.             ' + N'-- '
  12393.     insert into #proctext(procedure_text) values( @cmd )
  12394.  
  12395.     --
  12396.     -- script delete
  12397.     --
  12398.     select @cmd = N'
  12399.             delete ' + @qualname 
  12400.     insert into #proctext(procedure_text) values( @cmd )
  12401.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  12402.  
  12403.     --
  12404.     -- script the insert assignment
  12405.     --
  12406.     select @num_col = 0
  12407.     create table #worktab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  12408.     create table #worktab2 ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  12409.  
  12410.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  12411.     select colid from syscolumns where id = @objid order by colid asc
  12412.  
  12413.     OPEN hCColid
  12414.     FETCH hCColid INTO @this_col
  12415.     WHILE (@@fetch_status != -1)
  12416.     begin
  12417.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  12418.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  12419.         begin
  12420.             if rtrim(@ccoltype) not like N'timestamp' 
  12421.             begin
  12422.                 select @num_col = @num_col + 1
  12423.                 select @column_string = QUOTENAME(@colname)
  12424.                 select @var_string = N'@c' + cast(@this_col as nvarchar(4))
  12425.                 
  12426.                 if (@num_col > 1)
  12427.                 begin
  12428.                     select @column_string = N', ' + @column_string
  12429.                     select @var_string = N', ' +@var_string 
  12430.                 end
  12431.  
  12432.                 insert into #worktab(procedure_text) values( @column_string )                
  12433.                 insert into #worktab2(procedure_text) values( @var_string )                
  12434.                 
  12435.             end
  12436.         end
  12437.         FETCH hCColid INTO @this_col
  12438.     end
  12439.     CLOSE hCColid
  12440.     DEALLOCATE hCColid
  12441.  
  12442.     if (@num_col > 0)
  12443.     begin
  12444.         if (@identity_insert = 1)
  12445.         begin
  12446.             -- Only to call set if identity is not marked for 'not for repl'
  12447.             -- This is to avoid security failure of 'SET' for PAL users
  12448.             if not exists (select * from syscolumns where id = @objid and
  12449.                 ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  12450.             begin
  12451.                 select @cmd = N'
  12452.             set identity_insert ' + @qualname + N' on '
  12453.                 insert into #proctext(procedure_text) values( @cmd )
  12454.             end
  12455.         end
  12456.  
  12457.         select @cmd = N'
  12458.             insert into ' + @qualname + N'( '
  12459.         insert into #proctext(procedure_text) values( @cmd )
  12460.         insert into #proctext(procedure_text) 
  12461.             select procedure_text from #worktab order by c1 asc
  12462.         select @cmd = N' )
  12463.             values ( '
  12464.         insert into #proctext(procedure_text) values( @cmd )
  12465.         insert into #proctext(procedure_text) 
  12466.             select procedure_text from #worktab2 order by c1 asc
  12467.         select @cmd = N' )'
  12468.         insert into #proctext(procedure_text) values( @cmd )
  12469.  
  12470.         if (@identity_insert = 1)
  12471.         begin
  12472.             -- Only to call set if identity is not marked for 'not for repl'
  12473.             -- This is to avoid security failure of 'SET' for PAL users
  12474.             if not exists (select * from syscolumns where id = @objid and
  12475.                 ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  12476.             begin
  12477.                 select @cmd = N'
  12478.             set identity_insert ' + @qualname + N' off '
  12479.                 insert into #proctext(procedure_text) values( @cmd )
  12480.             end
  12481.         end
  12482.     end
  12483.     
  12484.     select @cmd = N'
  12485.             if (@@error != 0 or @retcode != 0)
  12486.                 return -1
  12487.         end
  12488.         else
  12489.             return -1
  12490.     end'
  12491.     insert into #proctext(procedure_text) values( @cmd )
  12492.  
  12493.     --
  12494.     -- all done
  12495.     --
  12496.     drop table #worktab
  12497.     drop table #worktab2
  12498.     return 0
  12499. END
  12500. go
  12501. exec dbo.sp_MS_marksystemobject sp_MSscript_insert_subwins
  12502. go
  12503.  
  12504. --------------------------------------------------------------------------------
  12505. --. sp_MSscript_insert_pubwins
  12506. --------------------------------------------------------------------------------
  12507.  
  12508. if exists (select * from sysobjects
  12509.     where type = 'P' and name = 'sp_MSscript_insert_pubwins')
  12510. drop procedure sp_MSscript_insert_pubwins
  12511. go
  12512. raiserror('Creating procedure sp_MSscript_insert_pubwins', 0,1)
  12513. go
  12514. create procedure sp_MSscript_insert_pubwins (
  12515.     @publication sysname,
  12516.     @article     sysname, 
  12517.     @objid int,
  12518.     @columns binary(32) )
  12519. AS
  12520. BEGIN
  12521.     declare @cmd nvarchar(4000)
  12522.             ,@artid int
  12523.             ,@pubid int
  12524.             ,@dest_table sysname
  12525.             ,@dest_owner nvarchar(260)
  12526.             ,@colname      sysname
  12527.             ,@ccoltype     sysname
  12528.             ,@this_col     int
  12529.             ,@rc           int
  12530.             ,@num_col      int
  12531.             ,@qualname nvarchar(512)
  12532.             ,@cast_str nvarchar(1000)
  12533.             ,@decl_str nvarchar(2000)
  12534.             ,@assign_str nvarchar(4000)
  12535.             ,@typestring nvarchar(100)
  12536.             ,@exec_str nvarchar(1000)
  12537.  
  12538.     --
  12539.     -- initialize the vars we will use
  12540.     --
  12541.     select @pubid = pubid from syspublications where name = @publication
  12542.     select @artid = artid, @dest_table = dest_table, @dest_owner = dest_owner
  12543.     from sysarticles where name = @article and pubid = @pubid
  12544.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  12545.                 else quotename(@dest_owner) + N'.' end
  12546.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  12547.                 
  12548.     --
  12549.     -- start script generation
  12550.     --
  12551.     select @cmd = N'
  12552.     else if (@error in (0, 547, 2601, 2627) and @execution_mode = @QPubWins)
  12553.     begin
  12554.         ' + N'--
  12555.         ' + N'-- Publisher Wins resolution
  12556.         ' + N'-- Find where we have to generate compensating action
  12557.         ' + N'--
  12558.         if (@rowcount = 1 and @error = 0)
  12559.         begin'
  12560.     insert into #proctext(procedure_text) values( @cmd )
  12561.  
  12562.     select @cmd = N'
  12563.             ' + N'--
  12564.             ' + N'-- No conflict for this command
  12565.             ' + N'-- Row does not exist
  12566.             ' + N'-- Generate delete compensating action
  12567.             ' + N'--
  12568.             select @cftcase = 23'
  12569.     insert into #proctext(procedure_text) values( @cmd )
  12570.  
  12571.     --
  12572.     -- Continue with scripting
  12573.     --
  12574.     select @cmd = N'
  12575.         end
  12576.         else if (@rowcount = 0 and @error in (547, 2601, 2627))
  12577.         begin
  12578.             ' + N'--
  12579.             ' + N'-- conflict for this command
  12580.             ' + N'-- Row already exists
  12581.             ' + N'-- generate update compensating action
  12582.             ' + N'-- DELETE compensating command + INSERT compensating command
  12583.             ' + N'--            
  12584.             select @cftcase = 21'
  12585.     insert into #proctext(procedure_text) values( @cmd )
  12586.  
  12587.     --
  12588.     -- continue with scripting
  12589.     --            
  12590.     select @cmd = N'        
  12591.         end
  12592.         else
  12593.             return -1
  12594.  
  12595.         ' + N'--
  12596.         ' + N'-- generate compensating command according to the cases
  12597.         ' + N'--'
  12598.     insert into #proctext(procedure_text) values( @cmd )
  12599.  
  12600.     select @cmd = N'
  12601.         if (@cftcase in (21,23))
  12602.         begin
  12603.             ' + N'--
  12604.             ' + N'-- delete compensating command
  12605.             ' + N'--'
  12606.     insert into #proctext(procedure_text) values( @cmd )
  12607.     
  12608.     --
  12609.     -- Generate the delete compensating code
  12610.     --
  12611.     select @cmd = N'
  12612.             select @cmd = ''DELETE ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  12613.         + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N' '' + '
  12614.     insert into #proctext(procedure_text) values( @cmd )
  12615.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'ins'
  12616.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  12617.  
  12618.     select @cmd = N'
  12619.         end
  12620.  
  12621.         if (@cftcase = 21)
  12622.         begin
  12623.             ' + N'--
  12624.             ' + N'-- insert compensating command
  12625.             ' + N'--'
  12626.     insert into #proctext(procedure_text) values( @cmd )
  12627.  
  12628.     --
  12629.     -- generate the compensating insert command
  12630.     --
  12631.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 0
  12632.  
  12633.     --
  12634.     -- continue with scripting
  12635.     --            
  12636.     select @cmd = N'        
  12637.         end
  12638.     end'
  12639.     insert into #proctext(procedure_text) values( @cmd )
  12640.  
  12641.     --
  12642.     -- all done
  12643.     --
  12644.     return 0    
  12645. END
  12646. go
  12647. exec dbo.sp_MS_marksystemobject sp_MSscript_insert_pubwins
  12648. go
  12649.  
  12650. --------------------------------------------------------------------------------
  12651. --. sp_MSscript_update_subwins
  12652. --------------------------------------------------------------------------------
  12653.  
  12654. if exists (select * from sysobjects
  12655.     where type = 'P' and name = 'sp_MSscript_update_subwins')
  12656. drop procedure sp_MSscript_update_subwins
  12657. go
  12658. raiserror('Creating procedure sp_MSscript_update_subwins', 0,1)
  12659. go
  12660. create procedure sp_MSscript_update_subwins (
  12661.     @publication sysname,
  12662.     @article     sysname, 
  12663.     @objid int,
  12664.     @columns binary(32),
  12665.     @identity_insert bit)
  12666. AS
  12667. BEGIN
  12668.     declare @cmd nvarchar(4000)
  12669.             ,@artid int
  12670.             ,@pubid int
  12671.             ,@qualname nvarchar(512)
  12672.             ,@column_string nvarchar(4000)
  12673.             ,@colname      sysname
  12674.             ,@ccoltype     sysname
  12675.             ,@this_col     int
  12676.             ,@rc           int
  12677.             ,@num_col      int
  12678.             ,@art_col      int
  12679.             ,@bitstr nvarchar(20)
  12680.             ,@bytestr nvarchar(20)
  12681.             ,@isset int
  12682.             ,@timestamp_subscribed bit
  12683.  
  12684.     --
  12685.     -- initialize the vars we will use
  12686.     --
  12687.     select @pubid = pubid from syspublications where name = @publication
  12688.     select @artid = artid from sysarticles 
  12689.         where name = @article and pubid = @pubid
  12690.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  12691.  
  12692.     --
  12693.     -- special flag for timestamp column subscription
  12694.     --
  12695.     if exists (select * from sysarticles where pubid = @pubid and
  12696.         name = @article and
  12697.         status & 32 <> 0)
  12698.         select @timestamp_subscribed = 1
  12699.     else
  12700.         select @timestamp_subscribed = 0
  12701.  
  12702.     --
  12703.     -- start scripting
  12704.     --
  12705.     select @cmd = N'
  12706.     if (@error in (0, 547, 2601, 2627) and @execution_mode = @QSubWins)
  12707.     begin
  12708.         ' + N'--
  12709.         ' + N'-- Subscriber Wins resolution
  12710.         ' + N'--
  12711.         select @retcode = 0
  12712.         if (@rowcount = 0)
  12713.         begin
  12714.             --
  12715.             -- Conflict for this command
  12716.             -- Check if PK update was being done
  12717.             --'
  12718.     insert into #proctext(procedure_text) values( @cmd )
  12719.     
  12720.     --
  12721.     -- script the PK update check
  12722.     --
  12723.     select @cmd = N'
  12724.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  12725.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  12726.     insert into #proctext(procedure_text) values( @cmd )
  12727.  
  12728.     select @cmd = N'
  12729.             if (@retcode = -1)
  12730.                 return -1
  12731.             if (@retcode = 0)
  12732.             begin
  12733.                 ' + N'--
  12734.                 ' + N'-- PK update is not being done
  12735.                 ' + N'-- '
  12736.     insert into #proctext(procedure_text) values( @cmd )
  12737.  
  12738.     --
  12739.     -- script the if exists code using OLD_PK
  12740.     --
  12741.     select @cmd = N'
  12742.                 if exists (select * from ' + @qualname 
  12743.     insert into #proctext(procedure_text) values( @cmd )
  12744.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  12745.     insert into #proctext(procedure_text) values( N' )')
  12746.     
  12747.     --
  12748.     -- continue scripting
  12749.     --
  12750.     select @cmd = N'
  12751.                 begin
  12752.                     ' + N'--
  12753.                     ' + N'-- row with OLD_PK exists
  12754.                     ' + N'-- update row with OLD_PK with queue values
  12755.                     ' + N'-- 
  12756.                     select @cftcase = 11
  12757.                 end'
  12758.     insert into #proctext(procedure_text) values( @cmd )
  12759.  
  12760.     select @cmd = N'
  12761.                 else
  12762.                 begin
  12763.                     ' + N'--
  12764.                     ' + N'-- row with OLD_PK does not exists
  12765.                     ' + N'-- insert row with queue values using OLD_PK
  12766.                     ' + N'-- 
  12767.                     select @cftcase = 13
  12768.                 end
  12769.             end'
  12770.     insert into #proctext(procedure_text) values( @cmd )
  12771.  
  12772.     --
  12773.     -- continue scripting
  12774.     --
  12775.     select @cmd = N'
  12776.             else
  12777.             begin
  12778.                 ' + N'--
  12779.                 ' + N'-- PK update is being done
  12780.                 ' + N'-- drop rows with OLD_PK, NEW_PK and insert row with queue values
  12781.                 ' + N'--
  12782.                 select @cftcase = 0'
  12783.     insert into #proctext(procedure_text) values( @cmd )
  12784.                 
  12785.     --
  12786.     -- script the if exists code using OLD_PK
  12787.     --
  12788.     select @cmd = N'
  12789.                 if exists (select * from ' + @qualname 
  12790.     insert into #proctext(procedure_text) values( @cmd )
  12791.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  12792.     insert into #proctext(procedure_text) values( N' )')
  12793.     
  12794.     --
  12795.     -- continue scripting
  12796.     --
  12797.     select @cmd = N'
  12798.                 begin
  12799.                     ' + N'--
  12800.                     ' + N'-- row with OLD_PK exists
  12801.                     ' + N'-- insert row with queue values using NEW_PK +
  12802.                     ' + N'-- delete row with OLD_PK
  12803.                     ' + N'-- 
  12804.                     select @cftcase = 14
  12805.                 end' 
  12806.     insert into #proctext(procedure_text) values( @cmd )
  12807.     
  12808.     --
  12809.     -- script the if exists code using NEW_PK
  12810.     --
  12811.     select @cmd = N'
  12812.                 if exists (select * from ' + @qualname 
  12813.     insert into #proctext(procedure_text) values( @cmd )
  12814.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  12815.     insert into #proctext(procedure_text) values( N' )')
  12816.  
  12817.     --
  12818.     -- continue scripting
  12819.     --
  12820.     select @cmd = N'
  12821.                 begin
  12822.                     ' + N'--
  12823.                     ' + N'-- row with NEW_PK exists
  12824.                     ' + N'-- case 15: rows with NEW_PK and OLD_PK exist
  12825.                     ' + N'-- update row with NEW_PK with queue values + 
  12826.                     ' + N'-- delete row with OLD_PK'
  12827.     insert into #proctext(procedure_text) values( @cmd )
  12828.  
  12829.     select @cmd = N'
  12830.                     ' + N'-- case 16: row with NEW_PK exists
  12831.                     ' + N'-- update row with NEW_PK with queue values
  12832.                     ' + N'--
  12833.                     select @cftcase = case when (@cftcase = 14) then 15 else 16 end
  12834.                 end'
  12835.     insert into #proctext(procedure_text) values( @cmd )
  12836.  
  12837.     select @cmd = N'
  12838.                 if (@cftcase = 0)
  12839.                 begin
  12840.                     ' + N'--
  12841.                     ' + N'-- no existing rows with OLD_PK or NEW_PK
  12842.                     ' + N'-- insert with queue values
  12843.                     ' + N'--
  12844.                     select @cftcase = 12
  12845.                 end
  12846.             end'
  12847.     insert into #proctext(procedure_text) values( @cmd )
  12848.  
  12849.     --
  12850.     -- continue scripting
  12851.     --
  12852.     select @cmd = N'
  12853.             ' + N'--
  12854.             ' + N'-- based on retcode do the resolution
  12855.             ' + N'-- 
  12856.             if (@cftcase in (12, 13, 14))
  12857.             begin
  12858.                 ' + N'--
  12859.                 ' + N'-- insert
  12860.                 ' + N'--'
  12861.     insert into #proctext(procedure_text) values( @cmd )
  12862.  
  12863.     --
  12864.     -- prepare the insert statement
  12865.     --
  12866.     if (@identity_insert = 1)
  12867.     begin
  12868.         -- Only to call set if identity is not marked for 'not for repl'
  12869.         -- This is to avoid security failure of 'SET' for PAL users
  12870.         if not exists (select * from syscolumns where id = @objid and
  12871.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  12872.         begin
  12873.             select @cmd = N'
  12874.                 set identity_insert ' + @qualname + N' on '
  12875.             insert into #proctext(procedure_text) values( @cmd )
  12876.         end
  12877.     end
  12878.  
  12879.     select @cmd = N'
  12880.                 insert into ' + @qualname + N'('
  12881.     insert into #proctext(procedure_text) values( @cmd )
  12882.  
  12883.     select @num_col = 0
  12884.             ,@art_col = 0
  12885.             ,@cmd = NULL
  12886.     create table #collisttab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  12887.     create table #worktab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  12888.     
  12889.  
  12890.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  12891.     select colid from dbo.syscolumns where id = @objid order by colid asc
  12892.  
  12893.     OPEN hCColid
  12894.     FETCH hCColid INTO @this_col
  12895.     WHILE (@@fetch_status != -1)
  12896.     begin
  12897.         -- Get the ordinal of the article partition or not.
  12898.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  12899.         if @isset = 0
  12900.         begin
  12901.             if ((@timestamp_subscribed = 1) and 
  12902.                     exists ( select * from dbo.syscolumns where id = @objid and colid = @this_col and xtype = 189))
  12903.                 select @art_col = @art_col + 1
  12904.         end
  12905.         else
  12906.             select @art_col = @art_col + 1
  12907.  
  12908.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  12909.         if @rc = 0 and EXISTS (select name from dbo.syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  12910.         begin
  12911.             if rtrim(@ccoltype) != N'timestamp' 
  12912.             begin
  12913.                 select @num_col = @num_col + 1
  12914.                         ,@bytestr = cast((1 + (@art_col-1) / 8 ) as nvarchar)
  12915.                         ,@bitstr =  cast( power(2, (@art_col-1) % 8 ) as nvarchar)
  12916.  
  12917.                 select @column_string = N'case substring(@bitmap,' + 
  12918.                     @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + 
  12919.                     N' then @c' + cast(@this_col as nvarchar(4)) + 
  12920.                     N' else @c' + cast(@this_col as nvarchar(4)) + N'_old end '
  12921.  
  12922.                 if (@num_col = 1)
  12923.                 begin
  12924.                     select @cmd = quotename(@colname)
  12925.                     select @column_string = N'
  12926.                     ' + @column_string
  12927.                 end
  12928.                 else
  12929.                 begin
  12930.                     select @cmd = @cmd + N',' + quotename(@colname)
  12931.                     select @column_string = N'
  12932.                     , ' + @column_string
  12933.                 end
  12934.  
  12935.                 -- transfer the column list string to table if large
  12936.                 if (len(@cmd) > 3000)
  12937.                 begin
  12938.                     insert into #collisttab(procedure_text) values( @cmd )
  12939.                     select @cmd = N' '
  12940.                 end
  12941.                 insert into #worktab(procedure_text) values( @column_string )
  12942.                 
  12943.             end
  12944.         end
  12945.         FETCH hCColid INTO @this_col
  12946.     end
  12947.     CLOSE hCColid
  12948.     DEALLOCATE hCColid
  12949.  
  12950.     -- transfer the remaining column list string to table
  12951.     insert into #collisttab(procedure_text) values( @cmd )
  12952.     
  12953.     insert into #proctext(procedure_text) 
  12954.         select procedure_text from #collisttab order by c1 asc
  12955.     select @cmd = N')
  12956.                 select '
  12957.     insert into #proctext(procedure_text) values( @cmd )
  12958.     insert into #proctext(procedure_text) 
  12959.         select procedure_text from #worktab order by c1 asc
  12960.  
  12961.     if (@identity_insert = 1)
  12962.     begin
  12963.         -- Only to call set if identity is not marked for 'not for repl'
  12964.         -- This is to avoid security failure of 'SET' for PAL users
  12965.         if not exists (select * from syscolumns where id = @objid and
  12966.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  12967.         begin
  12968.             select @cmd = N'
  12969.                 set identity_insert ' + @qualname + N' off '
  12970.             insert into #proctext(procedure_text) values( @cmd )
  12971.         end
  12972.     end
  12973.  
  12974.     --
  12975.     -- continue with scripting
  12976.     --
  12977.     select @cmd = N'
  12978.             end
  12979.  
  12980.             if (@cftcase = 11)
  12981.             begin
  12982.                 ' + N'--
  12983.                 ' + N'-- update using OLD_PK
  12984.                 ' + N'--'
  12985.     insert into #proctext(procedure_text) values( @cmd )
  12986.  
  12987.     --
  12988.     -- prepare the column list for update statement
  12989.     --
  12990.     select @num_col = 0
  12991.             ,@art_col = 0
  12992.     create table #worktab2 ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  12993.  
  12994.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  12995.     select colid from syscolumns where id = @objid order by colid asc
  12996.  
  12997.     OPEN hCColid
  12998.     FETCH hCColid INTO @this_col
  12999.     WHILE (@@fetch_status <> -1)
  13000.     begin
  13001.         -- Get the ordinal of the article partition or not.
  13002.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  13003.         if @isset = 0
  13004.         begin
  13005.             if ((@timestamp_subscribed = 1) and 
  13006.                     exists ( select * from dbo.syscolumns where id = @objid and colid = @this_col and xtype = 189))
  13007.                 select @art_col = @art_col + 1
  13008.         end
  13009.         else
  13010.             select @art_col = @art_col + 1
  13011.  
  13012.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  13013.         if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  13014.         begin
  13015.             if (rtrim(@ccoltype) != N'timestamp') and ColumnProperty(@objid, @colname, 'IsIdentity') != 1
  13016.             begin
  13017.                 select @num_col = @num_col + 1
  13018.                         ,@bytestr = cast((1 + (@art_col-1) / 8 ) as nvarchar)
  13019.                         ,@bitstr =  cast( power(2, (@art_col-1) % 8 ) as nvarchar)
  13020.  
  13021.                 select @column_string = quotename(@colname) + N' = case substring(@bitmap,' + 
  13022.                     @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + 
  13023.                     N' then @c' + cast(@this_col as nvarchar(4)) + 
  13024.                     N' else @c' + cast(@this_col as nvarchar(4)) + N'_old  end '
  13025.  
  13026.                 if (@num_col = 1)
  13027.                 begin
  13028.                     select @column_string = N'
  13029.                     ' + @column_string
  13030.                 end
  13031.                 else
  13032.                 begin
  13033.                     select @column_string = N'
  13034.                     , ' + @column_string
  13035.                 end
  13036.  
  13037.                 insert into #worktab2(procedure_text) values( @column_string )
  13038.                 
  13039.             end
  13040.         end
  13041.         FETCH hCColid INTO @this_col
  13042.     end
  13043.     CLOSE hCColid
  13044.     DEALLOCATE hCColid
  13045.  
  13046.     --
  13047.     -- script the update with OLD_PK statement
  13048.     --
  13049.     select @cmd = N'
  13050.                 update ' + @qualname + N' set '
  13051.     insert into #proctext(procedure_text) values( @cmd )
  13052.     insert into #proctext(procedure_text) 
  13053.         select procedure_text from #worktab2 order by c1 asc
  13054.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  13055.     
  13056.     --
  13057.     -- continue with scripting
  13058.     --
  13059.     select @cmd = N'
  13060.             end
  13061.  
  13062.             if (@cftcase in (15, 16))
  13063.             begin
  13064.                 ' + N'--
  13065.                 ' + N'-- update using NEW_PK
  13066.                 ' + N'--'
  13067.     insert into #proctext(procedure_text) values( @cmd )
  13068.                 
  13069.     --
  13070.     -- script the update with NEW_PK statement
  13071.     --
  13072.     select @cmd = N'
  13073.                 update ' + @qualname + N' set '
  13074.     insert into #proctext(procedure_text) values( @cmd )
  13075.     insert into #proctext(procedure_text) 
  13076.         select procedure_text from #worktab2 order by c1 asc
  13077.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  13078.     
  13079.     --
  13080.     -- continue with scripting
  13081.     --
  13082.     select @cmd = N'
  13083.             end
  13084.  
  13085.             if (@cftcase in (14, 15))
  13086.             begin
  13087.                 ' + N'--
  13088.                 ' + N'-- Do not delete if subscriber has already
  13089.                 ' + N'-- updated this row as part of this transaction
  13090.                 ' + N'--'
  13091.     insert into #proctext(procedure_text) values( @cmd )
  13092.  
  13093.     --
  13094.     -- script the if exists code using OLD_PK and msprepl_tran_version
  13095.     --
  13096.     select @cmd = N'
  13097.                 if not exists (select * from ' + @qualname 
  13098.     insert into #proctext(procedure_text) values( @cmd )
  13099.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'subwins_check', 'msrepl_tran_version', 0
  13100.     insert into #proctext(procedure_text) values( N' )')
  13101.  
  13102.     select @cmd = N'
  13103.                 begin
  13104.                     ' + N'-- 
  13105.                     ' + N'-- delete row with OLD_PK
  13106.                     ' + N'--'
  13107.     insert into #proctext(procedure_text) values( @cmd )
  13108.  
  13109.     --
  13110.     -- script delete with OLD_PK
  13111.     --
  13112.     select @cmd = N'
  13113.                     delete ' + @qualname 
  13114.     insert into #proctext(procedure_text) values( @cmd )
  13115.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  13116.  
  13117.     --
  13118.     -- continue with rest of scripting
  13119.     --
  13120.     select @cmd = N'
  13121.                 end
  13122.             end
  13123.     
  13124.             if (@@error != 0)
  13125.                 return -1
  13126.  
  13127.             select @retcode = 0
  13128.         end
  13129.     end'
  13130.     insert into #proctext(procedure_text) values( @cmd )
  13131.  
  13132.     --
  13133.     -- all done
  13134.     --
  13135.     drop table #collisttab
  13136.     drop table #worktab
  13137.     drop table #worktab2
  13138.     return 0
  13139. END
  13140. go
  13141. exec dbo.sp_MS_marksystemobject sp_MSscript_update_subwins
  13142. go
  13143.  
  13144. --------------------------------------------------------------------------------
  13145. --. sp_MSscript_update_pubwins
  13146. --------------------------------------------------------------------------------
  13147.  
  13148. if exists (select * from sysobjects
  13149.     where type = 'P' and name = 'sp_MSscript_update_pubwins')
  13150. drop procedure sp_MSscript_update_pubwins
  13151. go
  13152. raiserror('Creating procedure sp_MSscript_update_pubwins', 0,1)
  13153. go
  13154. create procedure sp_MSscript_update_pubwins (
  13155.     @publication sysname,
  13156.     @article     sysname, 
  13157.     @objid int,
  13158.     @columns binary(32) )
  13159. AS
  13160. BEGIN
  13161.     declare @cmd nvarchar(4000)
  13162.             ,@artid int
  13163.             ,@pubid int
  13164.             ,@dest_table sysname
  13165.             ,@dest_owner nvarchar(260)
  13166.             ,@colname      sysname
  13167.             ,@ccoltype     sysname
  13168.             ,@this_col     int
  13169.             ,@rc           int
  13170.             ,@num_col      int
  13171.             ,@qualname nvarchar(512)
  13172.             ,@cast_str nvarchar(1000)
  13173.             ,@decl_str nvarchar(2000)
  13174.             ,@assign_str nvarchar(4000)
  13175.             ,@typestring nvarchar(100)
  13176.             ,@exec_str nvarchar(1000)
  13177.             ,@fhasnonpkuniquekeys int
  13178.  
  13179.     --
  13180.     -- initialize the vars we will use
  13181.     --
  13182.     select @pubid = pubid from syspublications where name = @publication
  13183.     select @artid = artid, @dest_table = dest_table, @dest_owner = dest_owner
  13184.     from sysarticles where name = @article and pubid = @pubid
  13185.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  13186.                 else quotename(@dest_owner) + N'.' end
  13187.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  13188.  
  13189.     --
  13190.     -- start scripting
  13191.     --
  13192.     select @cmd = N'
  13193.     else if (@error in (0, 547, 2601, 2627) and @execution_mode = @QPubWins)
  13194.     begin '
  13195.     insert into #proctext(procedure_text) values( @cmd )
  13196.     --
  13197.     --  special declare for case when we have non PK unique keys
  13198.     --
  13199.     exec @fhasnonpkuniquekeys = dbo.sp_repltablehasnonpkuniquekey @tabid = @objid
  13200.     if (@fhasnonpkuniquekeys = 1)
  13201.     begin
  13202.          declare @spacer nvarchar(5)
  13203.             ,@art_col int
  13204.             ,@isset int
  13205.             ,@pkcolumns varbinary(32)
  13206.  
  13207.         select @cmd = N'
  13208.         declare '
  13209.             ,@spacer = N''
  13210.             ,@art_col = 1
  13211.         exec dbo.sp_getarticlepkcolbitmap @objid, @pkcolumns output
  13212.         declare #hccolid cursor local fast_forward for 
  13213.             select colid from syscolumns where id = @objid order by colid asc
  13214.         open #hccolid
  13215.         fetch #hccolid into @this_col
  13216.         while (@@fetch_status != -1)
  13217.         begin
  13218.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  13219.             if @isset != 0 and exists ( select name from syscolumns where id=@objid and colid=@this_col and iscomputed !=1 ) 
  13220.             begin
  13221.                 exec dbo.sp_gettypestring @objid, @this_col, @typestring output
  13222.                 select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  13223.                 select @art_col = @art_col + 1
  13224.                         ,@spacer = N','
  13225.  
  13226.                 if len( @cmd ) > 3000
  13227.                 begin
  13228.                     insert into #proctext(procedure_text) values( @cmd )
  13229.                     select @cmd = N''
  13230.                 end
  13231.             end
  13232.             fetch #hccolid into @this_col
  13233.         end
  13234.         close #hccolid
  13235.         deallocate #hccolid
  13236.         if len(@cmd) > 0
  13237.             insert into #proctext(procedure_text) values( @cmd )
  13238.     end
  13239.     --
  13240.     -- continue scripting
  13241.     --
  13242.     select @cmd = N'
  13243.         if (@rowcount = 1)
  13244.         begin
  13245.             ' + N'--
  13246.             ' + N'-- no conflict for this command
  13247.             ' + N'-- Check if PK update was being done
  13248.             ' + N'-- '
  13249.     insert into #proctext(procedure_text) values( @cmd )
  13250.  
  13251.     --
  13252.     -- script the PK update check
  13253.     --
  13254.     select @cmd = N'
  13255.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  13256.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  13257.     insert into #proctext(procedure_text) values( @cmd )
  13258.  
  13259.     --
  13260.     -- continue scripting
  13261.     --
  13262.     select @cmd = N'
  13263.             if (@retcode = -1)
  13264.                 return -1
  13265.             if (@retcode = 0)
  13266.             begin
  13267.                 ' + N'--
  13268.                 ' + N'-- PK update is not being done
  13269.                 ' + N'-- generate delete + insert compensating action with OLD_PK
  13270.                 ' + N'-- 
  13271.                 select @cftcase = 0
  13272.             end'
  13273.     insert into #proctext(procedure_text) values( @cmd )
  13274.  
  13275.     --
  13276.     -- continue scripting
  13277.     --
  13278.     select @cmd = N'
  13279.             else
  13280.             begin
  13281.                 ' + N'--
  13282.                 ' + N'-- PK update is being done
  13283.                 ' + N'-- generate delete + insert compensating action with OLD_PK
  13284.                 ' + N'-- generate delete compensating action with NEW_PK
  13285.                 ' + N'-- 
  13286.                 select @cftcase = 1
  13287.             end
  13288.         end'
  13289.     insert into #proctext(procedure_text) values( @cmd )
  13290.  
  13291.     --
  13292.     -- continue scripting
  13293.     --
  13294.     select @cmd = N'
  13295.         else
  13296.         begin
  13297.             ' + N'--
  13298.             ' + N'-- Conflict for this command
  13299.             ' + N'-- Check if PK update was being done
  13300.             ' + N'--'
  13301.     insert into #proctext(procedure_text) values( @cmd )
  13302.  
  13303.     --
  13304.     -- script the PK update check
  13305.     --
  13306.     select @cmd = N'
  13307.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  13308.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  13309.     insert into #proctext(procedure_text) values( @cmd )
  13310.  
  13311.     select @cmd = N'
  13312.             if (@retcode = -1)
  13313.                 return -1
  13314.             if (@retcode = 0)
  13315.             begin
  13316.                 ' + N'--
  13317.                 ' + N'-- PK update is not being done
  13318.                 ' + N'-- Now find the type of conflict
  13319.                 ' + N'-- '
  13320.     insert into #proctext(procedure_text) values( @cmd )
  13321.                 
  13322.     --
  13323.     -- script the if exists code using OLD_PK
  13324.     --
  13325.     select @cmd = N'
  13326.                 if exists (select * from ' + @qualname 
  13327.     insert into #proctext(procedure_text) values( @cmd )
  13328.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  13329.     insert into #proctext(procedure_text) values( N' )')
  13330.  
  13331.     --
  13332.     -- continue scripting
  13333.     --
  13334.     select @cmd = N'
  13335.                 begin
  13336.                     ' + N'--
  13337.                     ' + N'-- row exists
  13338.                     ' + N'-- generate delete + insert compensating action with OLD_PK
  13339.                     ' + N'--
  13340.                     select @cftcase = 11'
  13341.     insert into #proctext(procedure_text) values( @cmd )
  13342.     --
  13343.     -- special scripting for table with unique keys
  13344.     --
  13345.     if (@fhasnonpkuniquekeys = 1)
  13346.     begin
  13347.         select @cmd = N'
  13348.                     if (@error in (2601, 2627))
  13349.                     begin
  13350.                         ' + N'--
  13351.                         ' + N'-- Unique key violation
  13352.                         ' + N'-- case 15 : row with OLD_PK exist and row with NEW_UNK exists 
  13353.                         ' + N'-- generate delete compensating action with OLD_PK'
  13354.         insert into #proctext(procedure_text) values( @cmd )
  13355.         select @cmd = N'
  13356.                         ' + N'-- insert compensating action with OLD_PK 
  13357.                         ' + N'-- insert compensating action with rows that qualify the NEW_UNKEYS
  13358.                         ' + N'--
  13359.                         select @cftcase = 15
  13360.                     end'
  13361.         insert into #proctext(procedure_text) values( @cmd )
  13362.     end
  13363.     select @cmd = N'
  13364.                 end'
  13365.     insert into #proctext(procedure_text) values( @cmd )
  13366.     select @cmd = N'
  13367.                 else
  13368.                 begin
  13369.                     ' + N'--
  13370.                     ' + N'-- row does not exist
  13371.                     ' + N'-- generate delete compensating action with OLD_PK
  13372.                     ' + N'--
  13373.                     select @cftcase = 13'
  13374.     insert into #proctext(procedure_text) values( @cmd )
  13375.     --
  13376.     -- special scripting for table with unique keys
  13377.     --
  13378.     if (@fhasnonpkuniquekeys = 1)
  13379.     begin
  13380.         select @cmd = N'
  13381.                     if (@error in (2601, 2627))
  13382.                     begin
  13383.                         ' + N'--
  13384.                         ' + N'-- Unique key violation
  13385.                         ' + N'-- case 16 : rows with OLD_PK does not exist and row with NEW_UNK exists 
  13386.                         ' + N'-- generate delete compensating action with OLD_PK'
  13387.         insert into #proctext(procedure_text) values( @cmd )
  13388.         select @cmd = N'
  13389.                         ' + N'-- insert compensating action with rows that qualify the NEW_UNKEYS
  13390.                         ' + N'--
  13391.                         select @cftcase = 16
  13392.                     end'
  13393.         insert into #proctext(procedure_text) values( @cmd )
  13394.     end
  13395.     select @cmd = N'
  13396.                 end
  13397.             end'
  13398.     insert into #proctext(procedure_text) values( @cmd )
  13399.             
  13400.     --
  13401.     -- continue scripting
  13402.     --
  13403.     select @cmd = N'
  13404.             else
  13405.             begin
  13406.                 ' + N'--
  13407.                 ' + N'-- PK update is being done
  13408.                 ' + N'-- Now find the type of conflict
  13409.                 ' + N'-- 
  13410.                 select @cftcase = 0'
  13411.     insert into #proctext(procedure_text) values( @cmd )
  13412.                 
  13413.     --
  13414.     -- script the if exists code using OLD_PK
  13415.     --
  13416.     select @cmd = N'
  13417.                 if exists (select * from ' + @qualname 
  13418.     insert into #proctext(procedure_text) values( @cmd )
  13419.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  13420.     insert into #proctext(procedure_text) values( N' )')
  13421.  
  13422.     --
  13423.     -- continue scripting
  13424.     --
  13425.     select @cmd = N'
  13426.                 begin
  13427.                     ' + N'--
  13428.                     ' + N'-- row with OLD_PK exists
  13429.                     ' + N'-- generate delete compensating action with OLD_PK +
  13430.                     ' + N'-- insert compensating action with OLD_PK 
  13431.                     ' + N'--
  13432.                     select @cftcase = 14
  13433.                 end'
  13434.     insert into #proctext(procedure_text) values( @cmd )
  13435.  
  13436.     --
  13437.     -- script the if exists code using NEW_PK
  13438.     --
  13439.     select @cmd = N'
  13440.                 if exists (select * from ' + @qualname 
  13441.     insert into #proctext(procedure_text) values( @cmd )
  13442.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  13443.     insert into #proctext(procedure_text) values( N' )')
  13444.  
  13445.     --
  13446.     -- continue scripting
  13447.     --
  13448.     select @cmd = N'
  13449.                 begin
  13450.                     ' + N'--
  13451.                     ' + N'-- row with NEW_PK exists
  13452.                     ' + N'-- case 15: rows with NEW_PK and OLD_PK exist
  13453.                     ' + N'-- generate delete compensating actions with OLD_PK, NEW_PK +
  13454.                     ' + N'-- insert compensating actions with OLD_PK, NEW_PK' 
  13455.     insert into #proctext(procedure_text) values( @cmd )
  13456.     select @cmd = N'
  13457.                     ' + N'-- case 16: row with NEW_PK exists and OLD_PK does not exist
  13458.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK +
  13459.                     ' + N'-- insert compensating action with NEW_PK 
  13460.                     ' + N'--
  13461.                     select @cftcase = case when (@cftcase = 14) then 15 else 16 end
  13462.                 end'
  13463.     insert into #proctext(procedure_text) values( @cmd )
  13464.  
  13465.     --
  13466.     -- continue scripting
  13467.     --    
  13468.     select @cmd = N'
  13469.                 else
  13470.                 begin
  13471.                     ' + N'--
  13472.                     ' + N'-- row with NEW_PK does not exists
  13473.                     ' + N'-- case 12 : no existing rows with OLD_PK or NEW_PK
  13474.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK '
  13475.     insert into #proctext(procedure_text) values( @cmd )
  13476.     select @cmd = N'
  13477.                     ' + N'-- case 17 : row with OLD_PK exist and NEW_PK does not exist 
  13478.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK +
  13479.                     ' + N'-- insert compensating action with OLD_PK 
  13480.                     ' + N'-- 
  13481.                     select @cftcase = case when (@cftcase = 0) then 12 else 17 end 
  13482.                 end '
  13483.     insert into #proctext(procedure_text) values( @cmd )
  13484.     select @cmd = N'
  13485.             end
  13486.         end'         
  13487.     insert into #proctext(procedure_text) values( @cmd )
  13488.  
  13489.     --
  13490.     -- continue scripting
  13491.     --
  13492.     select @cmd = N'
  13493.         if (@cftcase in (0, 1, 11, 12, 13, 14, 15, 16, 17))
  13494.         begin
  13495.             ' + N'--
  13496.             ' + N'-- generation of delete compensating command with OLD_PK
  13497.             ' + N'--'
  13498.     insert into #proctext(procedure_text) values( @cmd )
  13499.  
  13500.     --
  13501.     -- generate delete compensating cmd with OLD_PK
  13502.     --
  13503.     select @cmd = N'
  13504.             select @cmd = ''DELETE ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  13505.         + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N' '' + '
  13506.     insert into #proctext(procedure_text) values( @cmd )
  13507.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'del'
  13508.     
  13509.     --
  13510.     -- script the sending command
  13511.     --
  13512.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  13513.     
  13514.     --
  13515.     -- continue scripting
  13516.     --
  13517.     select @cmd = N'
  13518.         end
  13519.         
  13520.         if (@cftcase in (1, 12, 15, 16, 17))
  13521.         begin
  13522.             ' + N'--
  13523.             ' + N'-- generation of delete compensating command with NEW_PK
  13524.             ' + N'--'
  13525.     insert into #proctext(procedure_text) values( @cmd )
  13526.  
  13527.     --
  13528.     -- generate delete compensating cmd with NEW_PK
  13529.     --
  13530.     select @cmd = N'
  13531.             select @cmd = ''DELETE ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  13532.         + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N' '' + '
  13533.     insert into #proctext(procedure_text) values( @cmd )
  13534.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'ins'
  13535.     
  13536.     --
  13537.     -- script the sending command
  13538.     --
  13539.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  13540.     
  13541.     --
  13542.     -- continue scripting
  13543.     --
  13544.     select @cmd = N'
  13545.         end
  13546.  
  13547.         if (@cftcase in (0, 1, 11, 14, 15, 17))
  13548.         begin
  13549.             ' + N'--
  13550.             ' + N'-- generate and send insert compensating command with OLD_PK
  13551.             ' + N'--'
  13552.     insert into #proctext(procedure_text) values( @cmd )
  13553.  
  13554.     --
  13555.     -- script compensating insert with OLD_PK
  13556.     --
  13557.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 1, 0
  13558.     
  13559.     --
  13560.     -- continue scripting
  13561.     --
  13562.     select @cmd = N'
  13563.         end
  13564.  
  13565.         if (@cftcase in (15, 16))
  13566.         begin
  13567.             ' + N'--
  13568.             ' + N'-- generate and send insert compensating command with NEW_PK
  13569.             ' + N'--'
  13570.     insert into #proctext(procedure_text) values( @cmd )
  13571.  
  13572.     --
  13573.     -- script compensating insert with NEW_PK
  13574.     --
  13575.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 0, 0
  13576.     
  13577.     --
  13578.     -- continue with scripting
  13579.     --
  13580.     select @cmd = N'
  13581.         end
  13582.         select @retcode = 0
  13583.     end'
  13584.     insert into #proctext(procedure_text) values( @cmd )
  13585.     
  13586.     --
  13587.     -- all done
  13588.     --
  13589.     return 0    
  13590. END
  13591. go
  13592. exec dbo.sp_MS_marksystemobject sp_MSscript_update_pubwins
  13593. go
  13594. --------------------------------------------------------------------------------
  13595. --. sp_MSscript_compensating_insert
  13596. --------------------------------------------------------------------------------
  13597.  
  13598. if exists (select * from sysobjects
  13599.     where type = 'P' and name = 'sp_MSscript_compensating_insert')
  13600. drop procedure sp_MSscript_compensating_insert
  13601. go
  13602. raiserror('Creating procedure sp_MSscript_compensating_insert', 0,1)
  13603. go
  13604. create procedure sp_MSscript_compensating_insert (
  13605.     @publication sysname,
  13606.     @article     sysname, 
  13607.     @objid int,
  13608.     @columns binary(32),
  13609.     @proctype    int = 1,        -- 0 = use new_pk, 1 = use old_pk
  13610.     @fdodeclare bit = 1        -- 0 = do not script declares for non PK unique key processing
  13611. )
  13612. AS
  13613. BEGIN
  13614.     declare @cmd nvarchar(4000)
  13615.             ,@artid int
  13616.             ,@pubid int
  13617.             ,@dest_table sysname
  13618.             ,@dest_owner nvarchar(260)
  13619.             ,@colname      sysname
  13620.             ,@ccoltype     sysname
  13621.             ,@this_col     int
  13622.             ,@rc           int
  13623.             ,@num_col      int
  13624.             ,@qualname nvarchar(540)
  13625.             ,@cast_str nvarchar(4000)
  13626.             ,@column_string nvarchar(4000)
  13627.             ,@ins_cmd nvarchar(255)
  13628.             ,@startoffset int
  13629.             ,@setprefix bit
  13630.             ,@commandlen int
  13631.             ,@fragmentlen int
  13632.             ,@collen int
  13633.             ,@first_time bit
  13634.             ,@fullcastlen int
  13635.             ,@splitlen int
  13636.             ,@pkcolumns varbinary(32)
  13637.             ,@fhasnonpkuniquekeys int
  13638.     declare @pkfetch table ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  13639.  
  13640.     --
  13641.     -- initialize the vars we will use
  13642.     --
  13643.     select @pubid = pubid from syspublications where name = @publication
  13644.     select @artid = artid, @dest_table = dest_table, 
  13645.         @dest_owner = dest_owner, @ins_cmd = ins_cmd from sysarticles 
  13646.     where name = @article and pubid = @pubid
  13647.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  13648.                 else quotename(@dest_owner) + N'.' end
  13649.             ,@fhasnonpkuniquekeys = 0
  13650.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  13651.  
  13652.     --
  13653.     -- Do we have non PK unique keys
  13654.     --
  13655.     exec @fhasnonpkuniquekeys = dbo.sp_repltablehasnonpkuniquekey @tabid = @objid
  13656.     if (@fhasnonpkuniquekeys = 1)
  13657.     begin
  13658.         --
  13659.         -- We have to generate commands based on where it was confict with PK or with other
  13660.         -- unique keys - so we will declare a cursor and walk through all the rows on publisher
  13661.         -- that could have conflicts with the subscriber row. For each row (PK) we will now perform
  13662.         -- compensating delete of non PK unique keys and then an compensating insert
  13663.         --
  13664.          declare @cmd2 nvarchar(4000)
  13665.             ,@cmd3 nvarchar(4000)
  13666.             ,@spacer nvarchar(5)
  13667.             ,@typestring sysname
  13668.             ,@art_col int
  13669.             ,@isset int
  13670.         declare @pkvars table ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  13671.         declare @pkcols table ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  13672.  
  13673.         --
  13674.         -- build some strings for PK columns and PK variables (@pkc1..)
  13675.         --
  13676.         exec dbo.sp_getarticlepkcolbitmap @objid, @pkcolumns output
  13677.         select @cmd = N''
  13678.             ,@cmd2 = N''
  13679.             ,@cmd3 = N''
  13680.             ,@spacer = N''
  13681.             ,@art_col = 1
  13682.         declare #hccolid cursor local fast_forward for 
  13683.             select colid, name from syscolumns where id = @objid order by colid asc
  13684.         open #hccolid
  13685.         fetch #hccolid into @this_col, @colname
  13686.         while (@@fetch_status != -1)
  13687.         begin
  13688.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  13689.             if @isset != 0 and (@colname is not null)
  13690.             begin
  13691.                 exec dbo.sp_gettypestring @objid, @this_col, @typestring output
  13692.                 select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  13693.                         ,@cmd2 = @cmd2 + @spacer + quotename(@colname)
  13694.                         ,@cmd3 = @cmd3 + @spacer + N'@pkc' + convert( nvarchar, @art_col )
  13695.  
  13696.                 select @art_col = @art_col + 1
  13697.                         ,@spacer = N','
  13698.  
  13699.                 if len( @cmd ) > 3000
  13700.                 begin
  13701.                     insert into @pkvars(procedure_text) values( @cmd )
  13702.                     select @cmd = N''
  13703.                 end
  13704.                 if len( @cmd2 ) > 3000
  13705.                 begin
  13706.                     insert into @pkcols(procedure_text) values( @cmd2 )
  13707.                     select @cmd2 = N''
  13708.                 end
  13709.                 if len( @cmd3 ) > 3000
  13710.                 begin
  13711.                     insert into @pkfetch(procedure_text) values( @cmd3 )
  13712.                     select @cmd3 = N''
  13713.                 end
  13714.             end
  13715.             fetch #hccolid into @this_col, @colname
  13716.         end
  13717.         close #hccolid
  13718.         deallocate #hccolid
  13719.         if len(@cmd) > 0
  13720.             insert into @pkvars(procedure_text) values( @cmd )
  13721.         if len(@cmd2) > 0
  13722.             insert into @pkcols(procedure_text) values( @cmd2 )
  13723.         if len(@cmd3) > 0
  13724.             insert into @pkfetch(procedure_text) values( @cmd3 )
  13725.         --
  13726.         -- script the PK variable declare now
  13727.         --
  13728.         if (@fdodeclare = 1)
  13729.         begin
  13730.             select @cmd = N'
  13731.             declare '
  13732.             insert into #proctext(procedure_text) values( @cmd )
  13733.             insert into #proctext(procedure_text) 
  13734.                 select procedure_text from @pkvars order by c1 asc
  13735.         end
  13736.         --
  13737.         -- script the cursor declare now
  13738.         --
  13739.         select @cmd = N'
  13740.             declare #hccompins cursor local fast_forward for 
  13741.                 select distinct '
  13742.         insert into #proctext(procedure_text) values( @cmd )
  13743.         insert into #proctext(procedure_text) 
  13744.             select procedure_text from @pkcols order by c1 asc
  13745.         select @cmd = N'
  13746.             from ' + @qualname 
  13747.         insert into #proctext(procedure_text) values( @cmd )
  13748.         if (@proctype = 1)
  13749.         begin
  13750.             exec @rc = sp_replscriptuniquekeywhereclause @tabid = @objid
  13751.                         ,@columns = @columns
  13752.                         ,@prefix = N'@c' 
  13753.                         ,@suffix = N'_old'
  13754.                         ,@mode = 5
  13755.         end
  13756.         else
  13757.         begin
  13758.             exec @rc = sp_replscriptuniquekeywhereclause @tabid = @objid
  13759.                         ,@columns = @columns
  13760.                         ,@prefix = N'@c' 
  13761.                         ,@mode = 5
  13762.         end
  13763.         --
  13764.         -- script the cursor open and fetch
  13765.         --
  13766.         select @cmd = N'
  13767.             open #hccompins
  13768.             fetch #hccompins into '
  13769.         insert into #proctext(procedure_text) values( @cmd )
  13770.         insert into #proctext(procedure_text) 
  13771.             select procedure_text from @pkfetch order by c1 asc
  13772.         select @cmd = N'
  13773.             while (@@fetch_status != -1)
  13774.             begin '
  13775.         insert into #proctext(procedure_text) values( @cmd )
  13776.         --
  13777.         -- The table has unique keys other than PK We will issue a compensating
  13778.         -- DELETE command to clear any rows that already have values for the 
  13779.         -- unique key columns - the subsequent compensating INSERT has to succeed.
  13780.         -- We will restore the current view of the publisher on to the subscriber
  13781.         -- if Subscriber had a rows that were different from publisher - then they will
  13782.         -- be resolved during the Queue reader run. So we are covered
  13783.         --
  13784.         select @cmd = N'
  13785.             ' + '--
  13786.             ' + '-- Issue a delete command for unique keys
  13787.             ' + '-- '
  13788.         insert into #proctext(procedure_text) values( @cmd )
  13789.         select @cmd = N'
  13790.             select @cmd = ''DELETE ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  13791.             + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N' '' + '
  13792.         insert into #proctext(procedure_text) values( @cmd )
  13793.         exec dbo.sp_replscriptuniquekeywhereclause @tabid = @objid
  13794.                     ,@columns = @columns
  13795.                     ,@mode = 4
  13796.         select @cmd = N'
  13797.             from ' + @qualname 
  13798.         insert into #proctext(procedure_text) values( @cmd )
  13799.         exec @rc = sp_scriptpkwhereclause @src_objid = @objid
  13800.                     ,@pkcolumns = @pkcolumns
  13801.                     ,@prefix = N'@pkc'
  13802.                     ,@artcolumns = @columns
  13803.         exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  13804.         select @cmd = N'
  13805.             ' + '--
  13806.             ' + '-- Issue the compensating insert for this PK row
  13807.             ' + '-- '
  13808.         insert into #proctext(procedure_text) values( @cmd )
  13809.     end
  13810.     
  13811.     --
  13812.     -- The compensating command will be split into one or more
  13813.     -- fragment commands if the length exceeds 3450 characters in length 
  13814.     -- (to accomodate compensating server/db names)
  13815.     -- For correctly estimating the length of the compensating command
  13816.     -- we have to take the max column length of the data into consideration along
  13817.     -- with the scripting command length
  13818.     --
  13819.  
  13820.     --
  13821.     -- use the insert command if available
  13822.     --
  13823.     select @commandlen = 0
  13824.             ,@setprefix = 1
  13825.  
  13826.     if (@ins_cmd = N'SQL')
  13827.     begin
  13828.         select @cmd = N'
  13829.             select @cmd = ''INSERT INTO ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  13830.                         + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N''' + 
  13831.                         '' SELECT '' + '
  13832.     end
  13833.     else
  13834.     begin
  13835.         select @cmd = N'
  13836.             select @cmd = ''EXEC ' + substring(@ins_cmd, 5, len(@ins_cmd) - 4) + N' '' + '
  13837.     end
  13838.     insert into #proctext(procedure_text) values( @cmd )
  13839.      select @commandlen = @commandlen + len(@cmd)
  13840.     
  13841.     select @num_col = 0
  13842.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  13843.     select colid, length from syscolumns where id = @objid order by colid asc
  13844.  
  13845.     OPEN hCColid
  13846.     FETCH hCColid INTO @this_col, @collen
  13847.     WHILE (@@fetch_status != -1)
  13848.     begin
  13849.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 1, @colname output, @ccoltype output
  13850.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  13851.         begin
  13852.             if rtrim(@ccoltype) not like N'timestamp' 
  13853.             begin
  13854.                 select @num_col = @num_col + 1
  13855.  
  13856.                 --
  13857.                 -- Compute the command fragment length needed for this column
  13858.                 -- based on the coltype
  13859.                 --                
  13860.                 if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('ntext','text','image'))
  13861.                 begin
  13862.                     --
  13863.                     -- For compensating commands we have to include the text and image data
  13864.                     -- as the custom procs used by Distribution process expects them - as it
  13865.                     -- done for regular transactional replication - but we will only send NULLs
  13866.                     -- as it is not possible to ascertain the size of the data during the generation
  13867.                     --        
  13868.                     select @cast_str = N' ''null'' '
  13869.                     select @fullcastlen = len(@cast_str)
  13870.                     select @fragmentlen = @fullcastlen + 4 + @collen
  13871.                 end
  13872.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  13873.                 begin
  13874.                     if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('nvarchar', 'nchar'))
  13875.                         select @collen = (@collen / 2)
  13876.     
  13877.                     select @cast_str = case 
  13878.                             when (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('nvarchar', 'nchar'))
  13879.                                 then N' ISNULL(''N'''''' + master.dbo.fn_MSgensqescstr(' + quotename(@colname) + N') collate database_default + '''''''', ''null'') '
  13880.                                 else N' ISNULL('''''''' + master.dbo.fn_MSgensqescstr(' + quotename(@colname) + N') collate database_default + '''''''', ''null'') '
  13881.                             end
  13882.        
  13883.                     select @fullcastlen = len(@cast_str)
  13884.                     select @fragmentlen = @fullcastlen + 4 + @collen
  13885.                 end
  13886.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  13887.                 begin
  13888.                     --
  13889.                     -- each byte has 2 nibbles - we need a char to represent each nibble
  13890.                     --
  13891.                     select @collen = @collen * 2
  13892.                     select @cast_str = N' ISNULL(master.dbo.fn_varbintohexsubstring(1,' + quotename(@colname) + N',1,0) collate database_default, ''null'') '
  13893.                     select @fullcastlen = len(@cast_str)
  13894.                     select @fragmentlen = @fullcastlen + 4 + @collen + 2
  13895.                 end
  13896.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  13897.                 begin
  13898.                     select @collen = 40
  13899.                     select @cast_str = N' ISNULL(CAST(' + quotename(@colname) + N' as nvarchar), ''null'') '
  13900.                     select @fragmentlen = len(@cast_str) + @collen
  13901.                 end
  13902.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('money','smallmoney'))
  13903.                 begin
  13904.                     select @collen = 40
  13905.                     select @cast_str = N' ISNULL(CONVERT(nvarchar(40),' + quotename(@colname) + N',2), ''null'') '
  13906.                     select @fragmentlen = len(@cast_str) + @collen
  13907.                 end
  13908.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'uniqueidentifier')
  13909.                 begin
  13910.                     select @collen = 40
  13911.                     select @cast_str = N' ISNULL('''''''' + CAST(' + quotename(@colname) + N' as nvarchar(40)) + '''''''', ''null'') '
  13912.                     select @fragmentlen = len(@cast_str) + @collen
  13913.                 end
  13914.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('datetime','smalldatetime'))
  13915.                 begin
  13916.                     select @collen = 40
  13917.                     select @cast_str = N' ISNULL('''''''' + CONVERT(nvarchar(40), ' + quotename(@colname) + N', 112) + N'' '' +  CONVERT(nvarchar(40), ' + quotename(@colname) + N', 114) + '''''''', ''null'') '
  13918.                     select @fragmentlen = len(@cast_str) + @collen
  13919.                 end
  13920.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'sql_variant')
  13921.                 begin
  13922.                     --
  13923.                     -- need to revisit this later
  13924.                     --
  13925.                     select @cast_str = N' ISNULL(master.dbo.fn_sqlvarbasetostr(' + quotename(@colname) + N' ) collate database_default, ''null'') '
  13926.                     select @fragmentlen = len(@cast_str) + @collen
  13927.                 end                    
  13928.                 else
  13929.                 begin
  13930.                     select @collen = 40
  13931.                     select @cast_str = N' ISNULL(CAST(' + quotename(@colname) + N' as nvarchar), ''null'') '
  13932.                     select @fragmentlen = len(@cast_str) + @collen
  13933.                 end
  13934.             
  13935.                 --
  13936.                 -- for fixed datatypes - we will not split the data at all we will
  13937.                 -- flush the command script and continue
  13938.                 -- for varying/large datatypes, we will have to split data if necessary
  13939.                 --
  13940.                 if ((lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar','binary','varbinary')) 
  13941.                         and (@fragmentlen + @commandlen > 3450))
  13942.                 begin
  13943.                      --
  13944.                      -- the column length is too big, we have to break the data string
  13945.                      -- initialize
  13946.                      --
  13947.                     if (@num_col = 1)
  13948.                     begin
  13949.                         select @column_string = N'
  13950.                 ' 
  13951.                     end
  13952.                     else
  13953.                     begin
  13954.                         select @column_string = N'
  13955.                 + '','' + ' 
  13956.                     end
  13957.  
  13958.                     --
  13959.                     -- use substring to break the string value in the
  13960.                     -- compensating command
  13961.                     --
  13962.                     select @first_time = 1
  13963.                             ,@startoffset = 1
  13964.                     while (@collen > 0)
  13965.                     begin
  13966.                          select @splitlen = case when ((@first_time = 1) or (@collen > 3450))
  13967.                                                  then (3450 - @commandlen - 30 - @fullcastlen)
  13968.                                                  else @collen end
  13969.                          if (@splitlen < 1)
  13970.                          begin
  13971.                              --
  13972.                              -- we have overcompensated the splitlen
  13973.                              -- set to half of the column length
  13974.                              --
  13975.                              select @splitlen = @collen / 2
  13976.                          end
  13977.  
  13978.                         --
  13979.                         -- Do we need to put quotes (many datatypes need it)
  13980.                         --
  13981.                          if (@first_time = 1)
  13982.                          begin
  13983.                             if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  13984.                                 select @column_string = case 
  13985.                                     when (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('nvarchar', 'nchar'))
  13986.                                         then @column_string + N' ISNULL(''N'''''' + master.dbo.fn_MSgensqescstr( '
  13987.                                         else @column_string + N' ISNULL('''''''' + master.dbo.fn_MSgensqescstr( '
  13988.                                     end
  13989.                             else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  13990.                                 select @column_string = @column_string + N' ISNULL(master.dbo.fn_varbintohexsubstring(1,' 
  13991.                         end
  13992.                          else
  13993.                          begin
  13994.                             if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  13995.                                  select @column_string = N' + ISNULL(master.dbo.fn_MSgensqescstr( '
  13996.                             else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  13997.                                 select @column_string = @column_string + N' + ISNULL(master.dbo.fn_varbintohexsubstring(0,' 
  13998.                          end
  13999.  
  14000.                         --
  14001.                         -- prepare the substring script
  14002.                         --
  14003.                         if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  14004.                             select @cast_str = N'SUBSTRING(' + quotename(@colname) + N', ' + cast(@startoffset as nvarchar) + N', ' +  cast(@splitlen as nvarchar) + N')'
  14005.                         else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  14006.                             select @cast_str = quotename(@colname) + N', ' + cast(@startoffset as nvarchar) + N', ' +  cast((@splitlen/2) as nvarchar)
  14007.  
  14008.                         if (@first_time = 1)
  14009.                          begin
  14010.                             select @cast_str = @cast_str + N') collate database_default, ''null'') '
  14011.                                     ,@first_time = 0
  14012.                          end
  14013.                          else
  14014.                          begin
  14015.                             if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  14016.                             begin
  14017.                                 --
  14018.                                 -- for strings the last fragment needs the single
  14019.                                 -- quote to be added for the string
  14020.                                 --
  14021.                                 select @cast_str = @cast_str + N') collate database_default '
  14022.                                 select @cast_str = case 
  14023.                                     when (@collen - @splitlen < 1)
  14024.                                         then @cast_str + N'+ '''''''', '''') '                                            
  14025.                                         else @cast_str + N', '''') ' 
  14026.                                     end
  14027.                             end
  14028.                             else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  14029.                                 select @cast_str = @cast_str + N') collate database_default, '''') '
  14030.                         end
  14031.                                  
  14032.                         select @column_string = @column_string + @cast_str
  14033.                         insert into #proctext(procedure_text) values( @column_string )
  14034.  
  14035.                         if (@fragmentlen + @commandlen > 3450)
  14036.                         begin
  14037.                             select @cmd = N'
  14038.             from ' + @qualname 
  14039.                             insert into #proctext(procedure_text) values( @cmd )
  14040.                             --
  14041.                             -- script the where clause
  14042.                             --
  14043.                             if (@fhasnonpkuniquekeys = 1)
  14044.                             begin
  14045.                                 --
  14046.                                 -- Non PK unique keys
  14047.                                 -- we are in the cursor for qualifying row
  14048.                                 -- 
  14049.                                 exec dbo.sp_scriptpkwhereclause @src_objid = @objid
  14050.                                             ,@pkcolumns = @pkcolumns
  14051.                                             ,@prefix = N'@pkc'
  14052.                                             ,@artcolumns = @columns
  14053.                             end
  14054.                             else
  14055.                             begin
  14056.                                 --
  14057.                                 -- only PK unique key
  14058.                                 --
  14059.                                 if (@proctype = 1)
  14060.                                     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  14061.                                 else
  14062.                                     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  14063.                             end
  14064.                             --
  14065.                             -- Script the compensating send
  14066.                             --
  14067.                             exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  14068.                             if (@setprefix = 1)
  14069.                                 select @setprefix = 0
  14070.  
  14071.                             select @cmd = N'
  14072.             select @cmd = N''''' 
  14073.                             insert into #proctext(procedure_text) values( @cmd )
  14074.                             select @commandlen = 0
  14075.                         end
  14076.                         else
  14077.                             select @commandlen = @commandlen + len(@column_string)
  14078.  
  14079.                         --
  14080.                         -- update vars for next round
  14081.                         --
  14082.                         select @collen = @collen - @splitlen
  14083.                                 ,@column_string = N''
  14084.                                 ,@startoffset = case 
  14085.                                     when (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary')) 
  14086.                                         then (@splitlen/2) + @startoffset 
  14087.                                         else @splitlen + @startoffset 
  14088.                                     end
  14089.                         select @fragmentlen = @fullcastlen + 4 + @collen
  14090.                     end                            
  14091.  
  14092.                     --
  14093.                     -- we done with this column now
  14094.                     -- skip processing further and continue
  14095.                     --                        
  14096.                     select @commandlen = @commandlen + len(@column_string)
  14097.                  end
  14098.                  else
  14099.                  begin
  14100.                     --
  14101.                     -- Handling general fixed type column cases
  14102.                     --
  14103.                     if (@num_col = 1)
  14104.                     begin
  14105.                         select @column_string = N'
  14106.                 ' + @cast_str
  14107.                     end
  14108.                     else
  14109.                     begin
  14110.                         select @column_string = N'
  14111.                 + '','' + ' + @cast_str
  14112.                     end
  14113.  
  14114.                     --
  14115.                     -- check if we need to flush the command first
  14116.                     --
  14117.                     if (@fragmentlen + len(@column_string) + @commandlen > 3450)
  14118.                     begin
  14119.                         --
  14120.                         -- send this compensating command first
  14121.                         --
  14122.                         select @cmd = N'
  14123.             from ' + @qualname 
  14124.                         insert into #proctext(procedure_text) values( @cmd )
  14125.                         --
  14126.                         -- script the where clause
  14127.                         --
  14128.                         if (@fhasnonpkuniquekeys = 1)
  14129.                         begin
  14130.                             --
  14131.                             -- Non PK unique keys
  14132.                             -- we are in the cursor for qualifying row
  14133.                             -- 
  14134.                             exec dbo.sp_scriptpkwhereclause @src_objid = @objid
  14135.                                         ,@pkcolumns = @pkcolumns
  14136.                                         ,@prefix = N'@pkc'
  14137.                                         ,@artcolumns = @columns
  14138.                         end
  14139.                         else
  14140.                         begin
  14141.                             --
  14142.                             -- only PK unique key
  14143.                             --
  14144.                             if (@proctype = 1)
  14145.                                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  14146.                             else
  14147.                                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  14148.                         end
  14149.                         --
  14150.                         -- Script the compensating send
  14151.                         --
  14152.                         exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  14153.                         if (@setprefix = 1)
  14154.                             select @setprefix = 0
  14155.  
  14156.                         select @cmd = N'
  14157.             select @cmd = N'' ''' 
  14158.                         insert into #proctext(procedure_text) values( @cmd )
  14159.                         select @commandlen = 0                    
  14160.                     end
  14161.  
  14162.                     --
  14163.                     -- script out the column string
  14164.                     --
  14165.                     insert into #proctext(procedure_text) values( @column_string )
  14166.  
  14167.                     --
  14168.                     -- if we are processing sql_variants, flush the command again
  14169.                     --
  14170.                     if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'sql_variant')
  14171.                     begin
  14172.                         --
  14173.                         -- send this compensating command first
  14174.                         --
  14175.                         select @cmd = N'
  14176.             from ' + @qualname 
  14177.                         insert into #proctext(procedure_text) values( @cmd )
  14178.                         --
  14179.                         -- script the where clause
  14180.                         --
  14181.                         if (@fhasnonpkuniquekeys = 1)
  14182.                         begin
  14183.                             --
  14184.                             -- Non PK unique keys
  14185.                             -- we are in the cursor for qualifying row
  14186.                             -- 
  14187.                             exec dbo.sp_scriptpkwhereclause @src_objid = @objid
  14188.                                         ,@pkcolumns = @pkcolumns
  14189.                                         ,@prefix = N'@pkc'
  14190.                                         ,@artcolumns = @columns
  14191.                         end
  14192.                         else
  14193.                         begin
  14194.                             --
  14195.                             -- only PK unique key
  14196.                             --
  14197.                             if (@proctype = 1)
  14198.                                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  14199.                             else
  14200.                                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  14201.                         end
  14202.                         --
  14203.                         -- Script the compensating send
  14204.                         --
  14205.                         exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  14206.                         if (@setprefix = 1)
  14207.                             select @setprefix = 0
  14208.  
  14209.                         select @cmd = N'
  14210.             select @cmd = N'' ''' 
  14211.                         insert into #proctext(procedure_text) values( @cmd )
  14212.                         select @commandlen = 0                    
  14213.                     end
  14214.                     else
  14215.                         select @commandlen = @commandlen + @fragmentlen + len(@column_string)
  14216.                 end
  14217.             end
  14218.         end
  14219.  
  14220.         --
  14221.         -- process the next column
  14222.         --
  14223.         FETCH hCColid INTO @this_col, @collen
  14224.     end
  14225.     CLOSE hCColid
  14226.     DEALLOCATE hCColid
  14227.  
  14228.     --
  14229.     -- Check if we need to flush the command one more time (final)
  14230.     --
  14231.     if (@commandlen > 0)
  14232.     begin
  14233.         --
  14234.         -- send the last fragment of the command
  14235.         --
  14236.         select @cmd = N'
  14237.             from ' + @qualname 
  14238.         insert into #proctext(procedure_text) values( @cmd )
  14239.         --
  14240.         -- script the where clause
  14241.         --
  14242.         if (@fhasnonpkuniquekeys = 1)
  14243.         begin
  14244.             --
  14245.             -- Non PK unique keys
  14246.             -- we are in the cursor for qualifying row
  14247.             -- 
  14248.             exec dbo.sp_scriptpkwhereclause @src_objid = @objid
  14249.                         ,@pkcolumns = @pkcolumns
  14250.                         ,@prefix = N'@pkc'
  14251.                         ,@artcolumns = @columns
  14252.         end
  14253.         else
  14254.         begin
  14255.             --
  14256.             -- only PK unique key
  14257.             --
  14258.             if (@proctype = 1)
  14259.                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  14260.             else
  14261.                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  14262.         end
  14263.         --
  14264.         -- Script the compensating send
  14265.         --
  14266.         exec sp_MSscript_compensating_send @pubid, @artid, 0, @setprefix
  14267.     end
  14268.  
  14269.     --
  14270.     -- More scripting for non PK unique key case
  14271.     --
  14272.     if (@fhasnonpkuniquekeys = 1)
  14273.     begin
  14274.         --
  14275.         -- script the cursor fetch
  14276.         --
  14277.         select @cmd = N'
  14278.             fetch #hccompins into '
  14279.         insert into #proctext(procedure_text) values( @cmd )
  14280.         insert into #proctext(procedure_text) 
  14281.             select procedure_text from @pkfetch order by c1 asc
  14282.         --
  14283.         -- script the cursor close and deallocate
  14284.         --
  14285.         select @cmd = N'
  14286.             end
  14287.             close #hccompins
  14288.             deallocate #hccompins '
  14289.         insert into #proctext(procedure_text) values( @cmd )
  14290.     end
  14291.     --
  14292.     -- all done
  14293.     --
  14294.     return 0
  14295. END
  14296. go
  14297. exec dbo.sp_MS_marksystemobject sp_MSscript_compensating_insert
  14298. go
  14299.  
  14300. --------------------------------------------------------------------------------
  14301. --. sp_MSscript_endproc
  14302. --------------------------------------------------------------------------------
  14303.  
  14304. if exists (select * from sysobjects
  14305.     where type = 'P' and name = 'sp_MSscript_endproc')
  14306. drop procedure sp_MSscript_endproc
  14307. go
  14308. raiserror('Creating procedure sp_MSscript_endproc', 0,1)
  14309. go
  14310. create procedure sp_MSscript_endproc (
  14311.     @objid int, 
  14312.     @op_type varchar(3) = 'ins', -- 'ins', 'upd', 'del'
  14313.     @columns binary(32),
  14314.     @outvars nvarchar(4000),
  14315.     @queued_pub bit = 0
  14316. )
  14317. as
  14318. BEGIN
  14319.     declare @cmd nvarchar(4000)
  14320.     declare @qualname nvarchar(512)
  14321.  
  14322.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  14323.  
  14324.     --
  14325.     -- start scripting
  14326.     --
  14327.     select @cmd = N'
  14328.     ' + N'--
  14329.     ' + N'-- decide the return code
  14330.     ' + N'--
  14331.     if (@execution_mode = @immediate)
  14332.     begin
  14333.         if @error != 0
  14334.               return -1
  14335.         -- Return special code to indicate the subscriber row needs to be
  14336.         -- refreshed.
  14337.         if @rowcount = 0
  14338.               return 5
  14339.     end'
  14340.     insert into #proctext(procedure_text) values(@cmd)
  14341.  
  14342.     --
  14343.     -- operation specific stuff
  14344.     --
  14345.     if (@queued_pub = 1)
  14346.     begin
  14347.         if (@op_type = 'ins')
  14348.         begin
  14349.             select @cmd = N'
  14350.     if (@execution_mode = @QFirstPass)
  14351.     begin
  14352.         if (@rowcount = 0)
  14353.         begin
  14354.             if (@error in (547, 2601, 2627))
  14355.                 return 2 -- insert conflict
  14356.             else
  14357.                 return -1 -- error
  14358.         end
  14359.     end'
  14360.         end
  14361.         else if (@op_type = 'upd')
  14362.         begin
  14363.             select @cmd = N'
  14364.     if (@execution_mode = @QFirstPass)
  14365.     begin
  14366.         if (@rowcount = 0)
  14367.         begin
  14368.             if (@error in (0, 547, 2601, 2627))
  14369.                 return 1 -- update conflict
  14370.             else
  14371.                 return -1 -- error
  14372.         end
  14373.     end'
  14374.         end
  14375.         else if (@op_type = 'del')
  14376.         begin
  14377.             select @cmd = N'
  14378.     if (@execution_mode = @QFirstPass)
  14379.     begin
  14380.         if (@rowcount = 0)
  14381.         begin
  14382.             if (@error in (0, 547))
  14383.                 return 3 -- delete conflict
  14384.             else
  14385.                 return -1 -- error
  14386.         end
  14387.     end'
  14388.         end
  14389.         insert into #proctext(procedure_text) values(@cmd)
  14390.         
  14391.         --
  14392.         -- continue with scripting
  14393.         --
  14394.         select @cmd = N'
  14395.     
  14396.     if (@execution_mode in (@QPubWins, @QSubWins))
  14397.     begin        
  14398.         if (@@error != 0 or @retcode != 0)
  14399.             return -1 -- error
  14400.     end
  14401.     '
  14402.         insert into #proctext(procedure_text) values(@cmd)
  14403.     end
  14404.  
  14405.     --
  14406.     -- if we have output vars to assign do it now
  14407.     --
  14408.     if (@outvars is not null)
  14409.     begin   
  14410.         if @op_type = 'upd'
  14411.         begin
  14412.             --
  14413.             -- Script out pk var assigment that used in sp_MSscript_where_clause
  14414.             --
  14415.             exec dbo.sp_MSscript_pkvar_assignment @objid, @columns, 1
  14416.             insert into #proctext(procedure_text) values(N'
  14417.     ')
  14418.         end
  14419.  
  14420.         select @cmd = N'
  14421.     select ' + @outvars + N'
  14422.     from ' + @qualname 
  14423.         insert into #proctext(procedure_text) values( @cmd)
  14424.         insert into #proctext(procedure_text) values( N'
  14425.     ')
  14426.     
  14427.         if (@op_type = 'ins')
  14428.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new pk', null, 4
  14429.         else if (@op_type = 'upd')
  14430.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'old pk', null, 4
  14431.     end
  14432.  
  14433.     --
  14434.     -- Final part of the proc
  14435.     --
  14436.     select @cmd = N'
  14437.     
  14438.     ' + N'--
  14439.     ' + N'-- past all checks
  14440.     ' + N'--
  14441.     return 0
  14442. END
  14443. '
  14444.     insert into #proctext(procedure_text) values(@cmd)
  14445.     
  14446.     --
  14447.     -- all done
  14448.     --
  14449.     return 0
  14450. END
  14451. go
  14452. exec dbo.sp_MS_marksystemobject sp_MSscript_endproc
  14453. go
  14454. --------------------------------------------------------------------------------
  14455. --. sp_repltablehasnonpkuniquekey
  14456. --------------------------------------------------------------------------------
  14457.  
  14458. if exists (select * from sysobjects
  14459.     where type = 'P' and name = 'sp_repltablehasnonpkuniquekey')
  14460. drop procedure sp_repltablehasnonpkuniquekey
  14461. go
  14462. raiserror('Creating procedure sp_repltablehasnonpkuniquekey',0,-1)
  14463. go
  14464. create procedure sp_repltablehasnonpkuniquekey 
  14465. (
  14466.     @tabid int              -- id of the table
  14467. )
  14468. as
  14469. begin
  14470.     set nocount on
  14471.     declare @retcode int
  14472.     --
  14473.     -- security check - should be dbo or sysadmin
  14474.     --
  14475.     exec @retcode = dbo.sp_MSreplcheck_publish
  14476.     if @@ERROR != 0 or @retcode != 0
  14477.         return (1)
  14478.     --
  14479.     -- process if the object is a table and has index
  14480.     --
  14481.     if (ObjectProperty(@tabid, 'IsTable') = 1) and (ObjectProperty(@tabid, 'TableHasIndex') = 1)
  14482.     begin
  14483.         --
  14484.         -- Set return flag if it is Unique key but not PK
  14485.         --
  14486.         if exists (select indid from sysindexes 
  14487.                 where id = @tabid 
  14488.                     and indid > 0 and indid < 255
  14489.                     and (status & 2) != 0 and (status & 2048) = 0 )
  14490.         begin
  14491.             select @retcode = 1
  14492.         end
  14493.     end
  14494.     --
  14495.     -- all done
  14496.     --
  14497.     return @retcode
  14498. end
  14499. go
  14500. exec sp_MS_marksystemobject sp_repltablehasnonpkuniquekey
  14501. go
  14502.  
  14503. --------------------------------------------------------------------------------
  14504. --. sp_replscriptuniquekeywhereclause
  14505. --------------------------------------------------------------------------------
  14506.  
  14507. if exists (select * from sysobjects
  14508.     where type = 'P' and name = 'sp_replscriptuniquekeywhereclause')
  14509. drop procedure sp_replscriptuniquekeywhereclause
  14510. go
  14511. raiserror('Creating procedure sp_replscriptuniquekeywhereclause', 0,1)
  14512. go
  14513. create procedure sp_replscriptuniquekeywhereclause 
  14514. (
  14515.     @tabid int                                  -- id of the table
  14516.     ,@columns binary(32)                 -- column map for the article
  14517.     ,@prefix nvarchar(10) = '@c'       -- prefix for the scripted column variables
  14518.     ,@suffix nvarchar(10) = null       -- suffix for the scripted column variables
  14519.     ,@mode tinyint                           -- 1 = insert custom proc, 2 = upd custom proc non PK, 3 = upd custom proc PK only 4 = compensating delete, 5 = compensating insert cursor declare
  14520.     ,@paramcount int = null              -- Total number of parameters - needed for mode = 2 and 3
  14521.  )
  14522. as
  14523. begin
  14524.     set nocount on
  14525.     declare @retcode int
  14526.                 ,@indid int
  14527.                 ,@indstatus int
  14528.                 ,@indkey int
  14529.                 ,@qualname nvarchar(512)
  14530.                 ,@colname sysname
  14531.                 ,@var sysname
  14532.                 ,@artcol int
  14533.                 ,@thiscol int
  14534.                 ,@cmd nvarchar(4000)
  14535.                 ,@findexstarted bit
  14536.                 ,@fisfirstindex bit
  14537.     --
  14538.     -- constants
  14539.     --
  14540.                 ,@modeinscustproc tinyint
  14541.                 ,@modeupdcustprocnonpk tinyint
  14542.                 ,@modeupdcustprocpkonly tinyint
  14543.                 ,@modedelcompensating tinyint
  14544.                 ,@modeinscompensatingcursordeclare tinyint
  14545.  
  14546.     --
  14547.     -- initialize
  14548.     --
  14549.     select @modeinscustproc = 1
  14550.             ,@modeupdcustprocnonpk = 2
  14551.             ,@modeupdcustprocpkonly = 3
  14552.             ,@modedelcompensating = 4
  14553.             ,@modeinscompensatingcursordeclare = 5
  14554.     --
  14555.     -- security check - should be dbo or sysadmin
  14556.     --
  14557.     exec @retcode = dbo.sp_MSreplcheck_publish
  14558.     if @@error != 0 or @retcode != 0
  14559.         return (1)
  14560.     --
  14561.     -- process if the object is a table and has index
  14562.     --
  14563.     if (ObjectProperty(@tabid, 'IsTable') != 1) or (ObjectProperty(@tabid, 'TableHasIndex') != 1)
  14564.         return (1)
  14565.     --
  14566.     -- Get the qualified name of the table
  14567.     --
  14568.     exec @retcode = sp_MSget_qualified_name @tabid, @qualname OUTPUT
  14569.     if @@error != 0 or @retcode != 0 or @qualname is null
  14570.         return (1)
  14571.     --
  14572.     -- @columns cannot be null
  14573.     --
  14574.     if (@columns is null)
  14575.         return (1)
  14576.     --
  14577.     -- Check @mode
  14578.     --
  14579.     if (@mode not in (@modeinscustproc, @modeupdcustprocnonpk, @modeupdcustprocpkonly, @modedelcompensating, @modeinscompensatingcursordeclare))
  14580.     begin
  14581.         return (1)
  14582.     end
  14583.     --
  14584.     -- validate @paramcount
  14585.     --
  14586.     if ((@mode in (@modeupdcustprocnonpk,@modeupdcustprocpkonly)) and (@paramcount is null))
  14587.     begin
  14588.         return (1)
  14589.     end
  14590.     --
  14591.     -- enumerate all the unique indices
  14592.     -- The scripting will be done as follows :
  14593.     --      where (ui1k1 = @cx and ui1k2 = @cy ...) or (u2k1 = @cz and ...) ...
  14594.     -- If we are scripting for the cursor declare in insert compensating then it will be as follows:
  14595.     --      where (ui1k1 = @cx or ui1k2 = @cy ...) or (u2k1 = @cz or ...) ...
  14596.     --
  14597.     select @cmd = case when (@mode = @modedelcompensating) then N' '' where '
  14598.                             else N' where ' end
  14599.             ,@findexstarted = 0
  14600.             ,@fisfirstindex = 1
  14601.     declare #hcindid cursor local fast_forward for
  14602.         select indid, status from sysindexes 
  14603.                 where id = @tabid and (status & 2) != 0
  14604.                     and indid > 0 and indid < 255
  14605.                     order by indid asc
  14606.     open #hcindid
  14607.     fetch #hcindid into @indid, @indstatus
  14608.     while (@@fetch_status != -1)
  14609.     begin
  14610.         --
  14611.         -- If we are in @modedelcompensating or @modeupdcustprocnonpk mode skip processing the PK index
  14612.         -- If we are in @modeupdcustprocpkonly mode skip processing the non PK index
  14613.         --
  14614.         if ((@mode in (@modeupdcustprocnonpk,@modedelcompensating)) and (@indstatus & 2048) != 0) 
  14615.             or ((@mode = @modeupdcustprocpkonly) and (@indstatus & 2048) = 0)
  14616.         begin
  14617.             --
  14618.             -- fetch next unique index
  14619.             --
  14620.             fetch #hcindid into @indid, @indstatus
  14621.             continue
  14622.         end
  14623.         --
  14624.         -- Enumerate the keys in this index
  14625.         --
  14626.         select @indkey = 1
  14627.         while (@indkey <= 16)
  14628.         begin
  14629.             --
  14630.             -- get the column name for the key
  14631.             --
  14632.             select @colname = index_col(@qualname, @indid, @indkey)
  14633.             if (@colname is null) 
  14634.                 break
  14635.             --
  14636.             -- check if this column is enabled for replication
  14637.             --
  14638.             select @artcol = 0
  14639.             exec dbo.sp_MSget_col_position @tabid, @columns, @colname, NULL, @artcol output, 0, NULL, @thiscol output
  14640.             if (@artcol > 0)
  14641.             begin
  14642.                 --
  14643.                 -- check if we are scripting the first key for this index
  14644.                 --
  14645.                 if (@findexstarted = 1)
  14646.                 begin
  14647.                     select @cmd = case when (@mode = @modedelcompensating) then @cmd + N' + '' and '
  14648.                                             when (@mode = @modeinscompensatingcursordeclare) then @cmd + N' or ' 
  14649.                                             else @cmd + N' and ' end
  14650.                 end
  14651.                 else
  14652.                 begin
  14653.                     --
  14654.                     -- check if we are scripting the first index. 
  14655.                     --
  14656.                     if (@fisfirstindex = 0)
  14657.                     begin
  14658.                         select @cmd =  @cmd + N' or ' 
  14659.                     end
  14660.                     else
  14661.                     begin
  14662.                         select @fisfirstindex = 0
  14663.                     end
  14664.                     --
  14665.                     -- set @findexstarted while processing the first key
  14666.                     --
  14667.                     select @findexstarted = 1
  14668.                     select @cmd = @cmd + N' ( ' 
  14669.                 end
  14670.                 --
  14671.                 -- script this column
  14672.                 --
  14673.                 if (@mode = @modedelcompensating)
  14674.                 begin
  14675.                     --
  14676.                     -- scripting a compensating command - we are building a dynamic string
  14677.                     --
  14678.                     declare @ccoltype sysname
  14679.  
  14680.                     select @cmd = @cmd + quotename(@colname)                
  14681.                             ,@var = quotename(@colname)
  14682.                     exec dbo.sp_MSget_colinfo @tabid, @thiscol, @columns, 0, NULL, @ccoltype output
  14683.                     if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'varchar')
  14684.                         select @cmd = @cmd + N' = '' + ISNULL('''''''' + master.dbo.fn_MSgensqescstr(' + @var + N') collate database_default + '''''''', ''null'') '
  14685.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'nvarchar')
  14686.                         select @cmd = @cmd + N' = '' + ISNULL(''N'''''' + master.dbo.fn_MSgensqescstr(' + @var + N') collate database_default + '''''''', ''null'') '
  14687.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'char')
  14688.                         select @cmd = @cmd + N' = '' + ISNULL('''''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + @var + N') as nvarchar)) collate database_default + '''''''', ''null'') '
  14689.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'nchar')
  14690.                         select @cmd = @cmd + N' = '' + ISNULL(''N'''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + @var + N') as nvarchar)) collate database_default + '''''''', ''null'') '
  14691.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  14692.                         select @cmd = @cmd + N' = '' + ISNULL(master.dbo.fn_varbintohexstr(' + @var + N') collate database_default, ''null'') ' 
  14693.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  14694.                         select @cmd = @cmd + N' = '' + ISNULL(CAST(' + @var + N' as nvarchar), ''null'') '
  14695.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('money','smallmoney'))
  14696.                         select @cmd = @cmd + N' = '' + ISNULL(CONVERT(nvarchar(40),' + @var + N', 2), ''null'') '
  14697.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'uniqueidentifier')
  14698.                         select @cmd = @cmd + N' = '' + ISNULL('''''''' + CAST(' + @var + N' as nvarchar(40)) + '''''''', ''null'') '
  14699.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('datetime','smalldatetime'))
  14700.                         select @cmd = @cmd + N' = '' + ISNULL('''''''' + CONVERT(nvarchar(40), ' + @var + N', 112) + N'' '' + CONVERT(nvarchar(40), ' + @var + N', 114) + '''''''', ''null'') '    
  14701.                     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'sql_variant')
  14702.                         select @cmd = @cmd + N' = '' + ISNULL(master.dbo.fn_sqlvarbasetostr(' + @var + N' ) collate database_default, ''null'') '
  14703.                     else
  14704.                         select @cmd = @cmd + N' = '' + ISNULL(CAST(' + @var + N' as nvarchar), ''null'') '
  14705.                 end
  14706.                 else
  14707.                 begin
  14708.                     --
  14709.                     -- scripting for custom procs - static script
  14710.                     --
  14711.                     select @var = case when (@mode in (@modeupdcustprocnonpk,@modeupdcustprocpkonly)) 
  14712.                                                     then @prefix + cast((@artcol + @paramcount/2) as nvarchar(10))
  14713.                                                     else @prefix + cast(@artcol as nvarchar(10)) end
  14714.                     if (@suffix is not null)
  14715.                         select @var = @var + @suffix
  14716.                     --
  14717.                     -- Does the column allow NULLs
  14718.                     --
  14719.                     if (columnproperty( @tabid , @colname , 'AllowsNull' ) = 1)
  14720.                     begin
  14721.                         --
  14722.                         -- static scripting should handle NULL valued column
  14723.                         -- ((<@var> is null and <colname> is null) or (<@var> is not null and <colname> = <@var>)) 
  14724.                         --
  14725.                         select @cmd = @cmd + N'((' + @var + N' is null and ' + quotename(@colname) + N' is null) or (' 
  14726.                                                 + @var + N' is not null and ' + quotename(@colname) + N' = ' + @var + N'))' 
  14727.                     end
  14728.                     else
  14729.                     begin
  14730.                         --
  14731.                         -- static scripting does not need to check for NULL values
  14732.                         -- <colname> = <@var>
  14733.                         --
  14734.                         select @cmd = @cmd + quotename(@colname) + N' = ' + @var
  14735.                     end
  14736.                     --
  14737.                     -- special processing for @modeupdcustprocnonpk
  14738.                     --
  14739.                     if (@mode = @modeupdcustprocnonpk)
  14740.                     begin
  14741.                         select @cmd = @cmd + N' and ' + @prefix + cast((@artcol + @paramcount/2) as nvarchar(10))
  14742.                         if (@suffix is not null)
  14743.                             select @cmd = @cmd + @suffix
  14744.                         select @cmd = @cmd + N' != ' + @prefix + cast(@artcol as nvarchar(10))
  14745.                         if (@suffix is not null)
  14746.                             select @cmd = @cmd + @suffix
  14747.                     end
  14748.                 end
  14749.                 --
  14750.                 -- transfer command string to table if too large
  14751.                 --
  14752.                 if (len(@cmd) > 3000)
  14753.                     exec dbo.sp_MSflush_command @cmd output, 1, 0                
  14754.             end            
  14755.             --
  14756.             -- get the next key for the index
  14757.             --
  14758.             select @indkey = @indkey + 1
  14759.         end
  14760.         --
  14761.         -- done with current index
  14762.         --
  14763.         select @findexstarted = 0
  14764.                 ,@cmd = case when (@mode = @modedelcompensating) then @cmd + N' + '' ) '
  14765.                                             else @cmd + N' ) ' end
  14766.         --
  14767.         -- fetch next unique index
  14768.         --
  14769.         fetch #hcindid into @indid, @indstatus
  14770.     end
  14771.     close #hcindid
  14772.     deallocate #hcindid
  14773.     --
  14774.     -- Final flush
  14775.     --
  14776.     if (@mode = @modedelcompensating)
  14777.         select @cmd = @cmd + N''''
  14778.     if (len(@cmd) > 0)
  14779.         exec dbo.sp_MSflush_command @cmd output, 1, 0                
  14780.     --
  14781.     -- all done
  14782.     --
  14783.     return 0
  14784. end
  14785. go
  14786. exec sp_MS_marksystemobject sp_replscriptuniquekeywhereclause
  14787. go
  14788.  
  14789. --------------------------------------------------------------------------------
  14790. --. sp_MSgettrancftsrcrow
  14791. --------------------------------------------------------------------------------
  14792.  
  14793. if exists (select * from sysobjects
  14794.     where type = 'P' and name = 'sp_MSgettrancftsrcrow')
  14795. drop procedure sp_MSgettrancftsrcrow
  14796. go
  14797. raiserror('Creating procedure sp_MSgettrancftsrcrow',0,-1)
  14798. go
  14799. create procedure sp_MSgettrancftsrcrow ( 
  14800.     @tran_id sysname,
  14801.     @row_id sysname,
  14802.     @conflict_table nvarchar(256),
  14803.     @is_subscriber bit,
  14804.     @is_debug bit=0 )
  14805. as 
  14806. begin
  14807.     set nocount on
  14808.     declare @decllist nvarchar(4000)
  14809.             ,@sellist nvarchar(4000)
  14810.             ,@wherelist nvarchar(4000)
  14811.             ,@cmd nvarchar(4000)
  14812.             ,@cmdrow nvarchar(4000)
  14813.             ,@srctable sysname
  14814.             ,@srctabid int
  14815.             ,@srcowner sysname
  14816.             ,@columns  binary(32)
  14817.             ,@indid int
  14818.             ,@indkey int
  14819.             ,@key sysname
  14820.             ,@this_col int
  14821.             ,@col sysname
  14822.             ,@typestring nvarchar(60)
  14823.             ,@dbname sysname
  14824.             ,@retcode smallint
  14825.             ,@unqualified_cft_tab sysname
  14826.             ,@startoffset int
  14827.             
  14828.     --
  14829.     -- validate
  14830.     --
  14831.     if ((@tran_id is null) or (@row_id is null) or 
  14832.         (@conflict_table is null) or (@is_subscriber is null))
  14833.     begin
  14834.         raiserror('sp_MSgettrancftsrcrow(debug): @tran_id,@row_id,@conflict_table,@is_subscriber cannot be null', 16, 1)
  14835.         return (1)
  14836.     end
  14837.  
  14838.     --
  14839.     -- check if the conflict table is owner qualified
  14840.     --
  14841.     select @startoffset = charindex(N'].[', @conflict_table, 0)
  14842.     select @unqualified_cft_tab = case when (@startoffset > 0) 
  14843.         then substring(@conflict_table, @startoffset + 2, len(@conflict_table) - @startoffset - 1)
  14844.         else quotename(@conflict_table) end
  14845.         
  14846.     --
  14847.     -- get the source table info
  14848.     --
  14849.     if (@is_subscriber = 1)
  14850.     begin
  14851.         select @srcowner = owner, @srctable = dest_table, 
  14852.             @srctabid = OBJECT_ID(dest_table), @columns = columns
  14853.         from MSsubscription_articles
  14854.         where quotename(cft_table) = @unqualified_cft_tab
  14855.     end
  14856.     else
  14857.     begin
  14858.         select @srcowner = user_name(OBJECTPROPERTY(objid,'OwnerId')), @srctable = OBJECT_NAME(objid), 
  14859.             @srctabid = objid, @columns = columns
  14860.         from sysarticles a join sysarticleupdates b on
  14861.             a.pubid = b.pubid and 
  14862.             a.artid = b.artid
  14863.         where b.conflict_tableid = OBJECT_ID(@conflict_table)
  14864.     end
  14865.  
  14866.     --
  14867.     -- create code for the following :
  14868.     -- select the row of conflict with given tranid and insertdate
  14869.     -- retrieve the values of the PK/UI columns for the source table from this row in cft_table
  14870.     -- select all columns from source table using the values in a where clause for PK/UI
  14871.     --
  14872.  
  14873.     --
  14874.     -- PK/UI check for source table
  14875.     --
  14876.     exec @indid = dbo.sp_MStable_has_unique_index @srctabid
  14877.     if (@indid = 0)
  14878.     begin
  14879.         raiserror('sp_MSgettrancftsrcrow(debug):source table %s does not have unique index', 16, 1, @srctable)
  14880.         return (1)
  14881.     end
  14882.  
  14883.     --
  14884.     -- create temp tables
  14885.     --
  14886.     create table #decltext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  14887.     create table #seltext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  14888.     create table #wheretext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  14889.  
  14890.     --
  14891.     -- walk through each column in PK/UI and build parts of code
  14892.     --
  14893.     select @indkey = 1
  14894.     while (@indkey <= 16)
  14895.     begin    
  14896.         select @key = index_col(@srctable, @indid, @indkey)
  14897.         if (@key is null)
  14898.         begin
  14899.             select @indkey = 16
  14900.         end
  14901.         else
  14902.         begin
  14903.             --
  14904.             -- get the column index in the source table for this index key
  14905.             --
  14906.             exec dbo.sp_MSget_col_position @srctabid, @columns, @key, @col output, @this_col output
  14907.  
  14908.             --
  14909.             -- get the typestring for this column in source table
  14910.             --
  14911.             exec dbo.sp_gettypestring @srctabid, @this_col, @typestring OUTPUT
  14912.  
  14913.             --
  14914.             -- build command strings
  14915.             --
  14916.             if (@decllist is NULL)
  14917.                 select @decllist = N'declare @' + @col + N' ' + @typestring
  14918.             else
  14919.                 select @decllist = N' ,@' + @col + N' ' + @typestring
  14920.             
  14921.             if (@sellist is NULL)
  14922.                 select @sellist = N'select @' + @col + N' = ' + quotename(@key)
  14923.             else
  14924.                 select @sellist = N' ,@' + @col + N' = ' + quotename(@key)
  14925.                 
  14926.             if (@wherelist is NULL)
  14927.                 select @wherelist = N'where ' + quotename(@key) + N' = @' + @col
  14928.             else
  14929.                 select @wherelist = N' and ' + quotename(@key) + N' = @' + @col
  14930.  
  14931.             --
  14932.             -- store them in the temp tables
  14933.             --
  14934.             insert into #decltext(cmdtext) values(@decllist)
  14935.             insert into #seltext(cmdtext) values(@sellist)
  14936.             insert into #wheretext(cmdtext) values(@wherelist)
  14937.             
  14938.         end
  14939.         select @indkey = @indkey + 1
  14940.     end
  14941.  
  14942.     --
  14943.     -- Now put all the code in order in the codetext
  14944.     --
  14945.     if exists (select * from sysobjects where name = 'MSsrcrow_codetext')
  14946.         drop table MSsrcrow_codetext
  14947.         
  14948.     create table MSsrcrow_codetext ( step int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  14949.  
  14950.     insert into MSsrcrow_codetext(cmdtext)
  14951.         select cmdtext from #decltext order by c1
  14952.     insert into MSsrcrow_codetext(cmdtext) values (N' ')
  14953.     insert into MSsrcrow_codetext(cmdtext)
  14954.         select cmdtext from #seltext order by c1
  14955.     select @cmd = N' 
  14956.     from ' 
  14957.  
  14958.     if (@startoffset > 0)
  14959.         select @cmd = @cmd + @conflict_table
  14960.     else
  14961.         select @cmd = @cmd + quotename(@srcowner) + N'.' + @unqualified_cft_tab
  14962.         
  14963.     select @cmd = @cmd + N'
  14964.     where tranid = ''' + @tran_id + ''' and qcfttabrowid = ''' + @row_id + ''' '
  14965.     insert into MSsrcrow_codetext(cmdtext) values (@cmd)
  14966.     select @cmd = N'select * from ' + quotename(@srcowner) + N'.' + quotename(@srctable) + N' '
  14967.     insert into MSsrcrow_codetext(cmdtext) values (@cmd)
  14968.     insert into MSsrcrow_codetext(cmdtext)
  14969.         select cmdtext from #wheretext order by c1
  14970.  
  14971.     --
  14972.     -- now execute the code we just built
  14973.     --
  14974.     if (@is_debug = 0)
  14975.     begin
  14976.         --
  14977.         -- Build 139:
  14978.         -- NOTE xp_execresultset should work here but does not
  14979.         -- return for a long time. Using exec() - should revisit
  14980.         -- this for more stable builds
  14981.         --
  14982.         declare #srccursor cursor local FAST_FORWARD FOR 
  14983.         select cmdtext from MSsrcrow_codetext order by step 
  14984.         FOR READ ONLY
  14985.  
  14986.         select @cmd = N' '
  14987.         select @dbname = db_name()
  14988.         open #srccursor
  14989.         fetch #srccursor into @cmdrow
  14990.         while (@@FETCH_STATUS = 0)
  14991.         begin
  14992.             select @cmd = @cmd + @cmdrow
  14993.             fetch #srccursor into @cmdrow    
  14994.         end        
  14995.         close #srccursor
  14996.         deallocate #srccursor
  14997.         
  14998.         execute(@cmd)
  14999.         if (@@error != 0)
  15000.         begin
  15001.             raiserror('sp_MSgettrancftsrcrow(debug): execute() failed for [%s] in db [%s] ', 16, 1, @cmd, @dbname)
  15002.             return (1)
  15003.         end
  15004.  
  15005.     end
  15006.     else
  15007.         select cmdtext from MSsrcrow_codetext order by step 
  15008.  
  15009.     --
  15010.     -- all done
  15011.     --
  15012.     drop table MSsrcrow_codetext
  15013.     return 0
  15014. end
  15015. go
  15016. exec dbo.sp_MS_marksystemobject sp_MSgettrancftsrcrow
  15017. go
  15018. grant execute on dbo.sp_MSgettrancftsrcrow to public
  15019. go
  15020. --------------------------------------------------------------------------------
  15021. --. sp_check_for_sync_trigger
  15022. --------------------------------------------------------------------------------
  15023.  
  15024. if exists (select * from sysobjects
  15025.     where type = 'P' and name = 'sp_script_synctran_commands')
  15026. drop procedure sp_script_synctran_commands
  15027. go
  15028. raiserror('Creating procedure sp_script_synctran_commands', 0,1)
  15029. GO
  15030. CREATE PROCEDURE sp_script_synctran_commands(
  15031.     @publication sysname,    /* publication name */
  15032.     @article sysname = 'all'    /* article name, all means all article */
  15033. AS
  15034. begin
  15035.     declare @retcode int
  15036.  
  15037.     --
  15038.     -- security check
  15039.     --
  15040.     exec @retcode = dbo.sp_MSreplcheck_publish
  15041.     if @@error <> 0 or @retcode <> 0
  15042.     begin
  15043.         return (1)
  15044.     end
  15045.     --
  15046.     -- Generate the scripts by calling internal SP
  15047.     --
  15048.     exec @retcode = dbo.sp_MSget_synctran_commands 
  15049.         @publication = @publication,
  15050.         @article = @article,
  15051.         @command_only = 1
  15052.     if @retcode <> 0 or @@error <> 0
  15053.         return (1)
  15054. end
  15055. go
  15056. EXEC dbo.sp_MS_marksystemobject sp_script_synctran_commands
  15057. GO
  15058. grant execute on dbo.sp_script_synctran_commands to public
  15059. go
  15060.  
  15061. --------------------------------------------------------------------------------
  15062. --. sp_replsqlqgetrows
  15063. --------------------------------------------------------------------------------
  15064.  
  15065. if exists (select * from sysobjects
  15066.     where type = 'P' and name = 'sp_replsqlqgetrows')
  15067. drop procedure sp_replsqlqgetrows
  15068. go
  15069. raiserror('Creating procedure sp_replsqlqgetrows', 0,1)
  15070. go
  15071. create proc sp_replsqlqgetrows (
  15072.     @publisher         sysname
  15073.     ,@publisherdb     sysname
  15074.     ,@publication     sysname
  15075. )
  15076. as
  15077. begin
  15078.     set nocount on
  15079.     declare @retcode int
  15080.  
  15081.     --
  15082.     -- security check
  15083.     --
  15084.     exec @retcode = sp_MSreplcheck_subscribe
  15085.     if @@error <> 0 or @retcode <> 0
  15086.     begin
  15087.         return (1)
  15088.     end
  15089.     --
  15090.     -- return rows
  15091.     --
  15092.     if exists (select * from dbo.sysobjects where name = 'MSreplication_queue')
  15093.     begin
  15094.         select tranid, datalen, data, commandtype, insertdate, orderkey, cmdstate 
  15095.         from dbo.MSreplication_queue with (READPAST) 
  15096.         where UPPER(publisher) = UPPER(@publisher) 
  15097.             and publisher_db = @publisherdb 
  15098.             and publication = @publication
  15099.         order by orderkey, tranid 
  15100.  
  15101.         if (@@error != 0)
  15102.             return 1
  15103.     end
  15104.     else
  15105.     begin
  15106.         --
  15107.         -- create empty rowset
  15108.         --
  15109.         declare @nomesgs TABLE (tranid     sysname, datalen int, data varbinary(8000),
  15110.             commandtype int, insertdate datetime, orderkey bigint, cmdstate bit)
  15111.         select * from @nomesgs
  15112.     end
  15113.     
  15114.     --
  15115.     -- All done
  15116.     --
  15117.     return 0
  15118. end
  15119. go
  15120. exec dbo.sp_MS_marksystemobject sp_replsqlqgetrows
  15121. go
  15122. grant execute on dbo.sp_replsqlqgetrows to public
  15123. go
  15124. --------------------------------------------------------------------------------
  15125. --. sp_changesubstatus
  15126. --------------------------------------------------------------------------------
  15127. if exists (select * from sysobjects
  15128.      where type = 'P '
  15129.            and name = 'sp_changesubstatus')
  15130.     drop procedure sp_changesubstatus
  15131. go
  15132. print ''
  15133. print 'Creating procedure sp_changesubstatus'
  15134. go
  15135. CREATE PROCEDURE sp_changesubstatus (
  15136.     @publication sysname = '%',    /* publication name */
  15137.     @article sysname = '%',        /* article name */
  15138.     @subscriber sysname = '%',      /* subscriber name */
  15139.     @status sysname,                /* subscription status */
  15140.     @previous_status sysname=NULL,  /* previous subscription status */
  15141.     @destination_db sysname = '%',   /* destination database name */
  15142.  
  15143.     @frequency_type int = NULL,
  15144.     @frequency_interval int = NULL,
  15145.     @frequency_relative_interval int = NULL,
  15146.     @frequency_recurrence_factor int = NULL,
  15147.     @frequency_subday int = NULL,
  15148.     @frequency_subday_interval int = NULL,
  15149.     @active_start_time_of_day int = NULL,
  15150.     @active_end_time_of_day int = NULL,
  15151.     @active_start_date int = NULL,
  15152.     @active_end_date int = NULL,
  15153.     @optional_command_line nvarchar(4000) = NULL,
  15154.     @distribution_jobid binary(16) = NULL OUTPUT,
  15155.     @from_auto_sync bit = 0,
  15156.     @ignore_distributor bit = 0,
  15157.     -- Agent offload
  15158.     @offloadagent bit = 0,
  15159.     @offloadserver sysname = NULL,
  15160.     @dts_package_name sysname = NULL,
  15161.     @dts_package_password nvarchar(524) = NULL,
  15162.     @dts_package_location int = 0,
  15163.     @schemastabilityonly int = 0,
  15164.     @distribution_job_name sysname = NULL
  15165.  
  15166. ) AS
  15167.  
  15168.     SET NOCOUNT ON
  15169.     DECLARE @inactive tinyint
  15170.     DECLARE @subscribed tinyint
  15171.     DECLARE @active tinyint
  15172.     DECLARE @initiated tinyint
  15173.     DECLARE @public tinyint
  15174.     DECLARE @replicate_bit smallint
  15175.     DECLARE @msg nvarchar(255)
  15176.     DECLARE @prevstatid tinyint
  15177.     DECLARE @artid int
  15178.     DECLARE @tabid int
  15179.     DECLARE @srvid smallint
  15180.     DECLARE @statusid tinyint
  15181.     DECLARE @distributor sysname
  15182.     DECLARE @distribdb sysname
  15183.     DECLARE @distproc nvarchar (255)
  15184.     DECLARE @pub_db sysname
  15185.     DECLARE @dest_db sysname
  15186.     DECLARE @sub_name sysname
  15187.     DECLARE @sub_status tinyint
  15188.     DECLARE @sub_ts varbinary (16)
  15189.     DECLARE @non_sql_flag bit
  15190.     DECLARE @qcmd nvarchar (4000)
  15191.     DECLARE @cmd1 nvarchar (255)
  15192.     DECLARE @cmd2 nvarchar (255)
  15193.     DECLARE @cmd3 nvarchar (255)
  15194.     DECLARE @retcode int
  15195.     DECLARE @repl_freq tinyint
  15196.     DECLARE @art_type tinyint
  15197.     DECLARE @proccmd  nvarchar(255)
  15198.     DECLARE @procnum  smallint
  15199.     DECLARE @finished_real bit
  15200.     DECLARE @finished_virtual bit
  15201.     DECLARE @virtual_id smallint
  15202.     DECLARE @immediate_sync bit
  15203.     DECLARE @enabled_for_internet bit
  15204.     DECLARE @allow_anonymous bit
  15205.     DECLARE @subscription_type int
  15206.     DECLARE @xact_seqno binary(10)
  15207.     DECLARE @sync_type tinyint
  15208.     DECLARE @automatic tinyint
  15209.     DECLARE @bcp_char tinyint    
  15210.     DECLARE @concurrent_char tinyint    
  15211.  
  15212.     DECLARE @art_change bit
  15213.     declare @login_name sysname
  15214.  
  15215.     DECLARE @pubid int
  15216.     DECLARE @syncinit_lsn binary(10)
  15217.  
  15218.     DECLARE @f_syncstat_posted bit
  15219.  
  15220.     -- synctran
  15221.     DECLARE @update_mode tinyint
  15222.     DECLARE @art_name sysname
  15223.     declare @synctran tinyint
  15224.     declare @no_distproc bit
  15225.     declare @loopback_detection bit
  15226.     
  15227.     /*
  15228.     ** Initializations.
  15229.     */
  15230.     select @synctran = 1
  15231.             
  15232.     SELECT @automatic = 1
  15233.     SELECT @inactive = 0        /* Const: subscription status 'inactive' */
  15234.     SELECT @subscribed = 1      /* Const: subscription status 'subscribed' */
  15235.     SELECT @active = 2          /* Const: subscription status 'active' */
  15236.     SELECT @initiated = 3        /* Const: subscription status 'initiated' */
  15237.     SELECT @public = 0          /* Const: publication status 'public' */
  15238.     SELECT @pub_db = DB_NAME()
  15239.     SELECT @virtual_id = -1
  15240.     SELECT @art_change = 0
  15241.     select @bcp_char = 1
  15242.     select @concurrent_char = 4    
  15243.  
  15244.     SELECT @f_syncstat_posted = 0
  15245.  
  15246.     SELECT @replicate_bit = 2
  15247.  
  15248.     /* 
  15249.     ** Security Check.
  15250.     ** We use login_name stored in syssubscriptions to manage security 
  15251.     */
  15252.  
  15253.     /*
  15254.     ** Parameter Check:  @publication
  15255.     ** Check to make sure that the publication exists, that it's not NULL,
  15256.     ** and that it conforms to the rules for identifiers.
  15257.     */
  15258.  
  15259.     IF @publication IS NULL
  15260.         BEGIN
  15261.             RAISERROR (14043, 16, -1, '@publication')
  15262.             RETURN (1)
  15263.         END
  15264.  
  15265.     IF @publication <> '%'
  15266.         BEGIN
  15267.             EXECUTE @retcode = dbo.sp_validname @publication
  15268.             IF @@ERROR <> 0 OR @retcode <> 0
  15269.             RETURN (1)
  15270.         END
  15271.  
  15272.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication)
  15273.         BEGIN
  15274.         IF @publication = '%'
  15275.                 RAISERROR (14008, 11, -1)
  15276.         ELSE
  15277.                 RAISERROR (20026, 11, -1, @publication)
  15278.         RETURN (1)
  15279.         END
  15280.  
  15281.     /*
  15282.     ** Parameter Check:  @article
  15283.     ** Check to make sure that the article exists, that it's not null,
  15284.     ** and that it conforms to the rules for identifiers.
  15285.     */
  15286.  
  15287.     IF @article IS NULL
  15288.         BEGIN
  15289.             RAISERROR (14043, 16, -1, '@article')
  15290.             RETURN (1)
  15291.         END
  15292.  
  15293.     /*
  15294.     IF @article <> '%'
  15295.         BEGIN
  15296.             EXECUTE @retcode = dbo.sp_validname @article
  15297.             IF @@ERROR <> 0 OR @retcode <> 0
  15298.             RETURN (1)
  15299.         END
  15300.     */
  15301.  
  15302.     IF NOT EXISTS (SELECT *
  15303.                      FROM sysextendedarticlesview a,
  15304.                           syspublications b
  15305.                 WHERE a.name LIKE @article
  15306.                       AND a.pubid = b.pubid
  15307.                       AND b.name LIKE @publication)
  15308.  
  15309.         BEGIN
  15310.         IF @article = '%'
  15311.                 RAISERROR (14009, 11, -1, @publication)
  15312.         ELSE
  15313.                 RAISERROR (20027, 11, -1, @article)
  15314.         RETURN (1)
  15315.         END
  15316.  
  15317.     /*
  15318.     ** Parameter Check:  @subscriber
  15319.     ** Check to make sure that the subscriber exists, that it is not NULL,
  15320.     ** and that it conforms to the rules for identifiers.
  15321.     ** Null subscriber represents virtual subscriptions
  15322.     */
  15323.  
  15324.     IF @subscriber IS NOT NULL AND @subscriber <> '%'
  15325.     BEGIN    
  15326.         EXECUTE @retcode = dbo.sp_validname @subscriber
  15327.         IF @@ERROR <> 0 OR @retcode <> 0
  15328.         RETURN (1)
  15329.  
  15330.         IF NOT EXISTS (SELECT *
  15331.                          FROM master..sysservers
  15332.                         WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  15333.                           AND (srvstatus & 4) <> 0)
  15334.  
  15335.             BEGIN
  15336.                 RAISERROR (14063, 11, -1)
  15337.                 RETURN (1)
  15338.             END
  15339.     END
  15340.  
  15341.     /*
  15342.     ** Parameter Check: @status.
  15343.     ** Set the @statusid according to the @status value.  Values can be
  15344.     ** any of the following:
  15345.     **
  15346.     **      status      statusid
  15347.     **      =========   ========
  15348.     **      inactive           0
  15349.     **      subscribed         1
  15350.     **      active             2
  15351.     **        initiated          3
  15352.     */
  15353.  
  15354.     IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('active', 'subscribed', 'inactive', 'initiated')
  15355.         BEGIN
  15356.             RAISERROR (14065, 16, -1)
  15357.         RETURN (1)
  15358.         END
  15359.  
  15360.     IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) IN ('initiated')
  15361.         SELECT @statusid = @initiated
  15362.     ELSE IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) IN ('active')
  15363.         SELECT @statusid = @active
  15364.     ELSE IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) IN ('subscribed')
  15365.         SELECT @statusid = @subscribed
  15366.     ELSE
  15367.         SELECT @statusid = @inactive
  15368.  
  15369.     /*
  15370.     ** Parameter Check: @previous_status.
  15371.     ** Set the @prevstatid according to the @previous_status value.
  15372.     ** Values can be any of the following:
  15373.     **
  15374.     **      previous_status      prevstatid
  15375.     **      ===============      ==========
  15376.     **      inactive                      0
  15377.     **      subscribed                    1
  15378.     **      active                        2
  15379.     **        initiated                      3
  15380.     */
  15381.  
  15382.     IF @previous_status IS NOT NULL
  15383.     BEGIN
  15384.         IF LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('initiated','active', 'subscribed', 'inactive')
  15385.         BEGIN
  15386.             RAISERROR (14066, 16, -1)
  15387.             RETURN (1)
  15388.         END
  15389.  
  15390.         IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) = LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS)
  15391.         BEGIN
  15392.             RAISERROR (14067, 16, -1)
  15393.             RETURN (1)
  15394.         END
  15395.  
  15396.         IF LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS) IN ('initiated')
  15397.             SELECT @prevstatid = @initiated
  15398.         ELSE IF LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS) IN ('active')
  15399.             SELECT @prevstatid = @active
  15400.         ELSE IF LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS) IN ('subscribed')
  15401.             SELECT @prevstatid = @subscribed
  15402.         ELSE
  15403.            SELECT @prevstatid = @inactive
  15404.     END
  15405.  
  15406.     /*
  15407.     ** Parameter Check: @destination_db.
  15408.     ** Set @destination_db to current database if not specified.  Make
  15409.     ** sure that the @destination_db conforms to the rules for identifiers.
  15410.     */
  15411.  
  15412.     IF @destination_db <> '%' 
  15413.     BEGIN
  15414.         EXECUTE @retcode = dbo.sp_validname @destination_db
  15415.         IF @retcode <> 0
  15416.         RETURN (1)
  15417.     END
  15418.  
  15419.     /*
  15420.     ** Get distribution server information for remote RPC
  15421.     ** subscription calls.
  15422.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  15423.     */
  15424.     if @ignore_distributor = 1 
  15425.         select @no_distproc = 1
  15426.     else
  15427.         select @no_distproc = 0
  15428.  
  15429.     IF @no_distproc = 0 --and @from_auto_sync = 0 
  15430.     BEGIN
  15431.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  15432.                                            @distribdb = @distribdb OUTPUT
  15433.  
  15434.         IF @@ERROR <> 0
  15435.         BEGIN
  15436.             RAISERROR (14071, 16, -1)
  15437.             RETURN (1)
  15438.         END
  15439.  
  15440.         IF @retcode <> 0 OR @distribdb IS NULL OR @distributor IS NULL
  15441.         BEGIN
  15442.             RAISERROR (14071, 16, -1)
  15443.             RETURN (1)
  15444.         END
  15445.     END
  15446.  
  15447.  
  15448.     create table #sysextendedarticlesview
  15449.     (
  15450.     artid               int                 NULL,
  15451.     columns             varbinary(32)       NULL,
  15452.     creation_script     nvarchar(255)       collate database_default null,
  15453.     del_cmd             nvarchar(255)       collate database_default null,
  15454.     description         nvarchar(255)       collate database_default null,
  15455.     dest_table          sysname             collate database_default null,
  15456.     filter              int                 NULL,
  15457.     filter_clause       ntext               NULL,
  15458.     ins_cmd             nvarchar(255)       collate database_default null,
  15459.     name                sysname             collate database_default null,
  15460.     objid               int                 NULL,
  15461.     pubid               int                 NULL,
  15462.     pre_creation_cmd    tinyint             NULL,
  15463.     status              tinyint             NULL,
  15464.     sync_objid          int                 NULL,
  15465.     type                tinyint             NULL,
  15466.     upd_cmd             nvarchar(255)       collate database_default null,
  15467.     schema_option       binary(8)           NULL,
  15468.     dest_owner          sysname             collate database_default null
  15469.     )
  15470.  
  15471.     insert into #sysextendedarticlesview select * from sysextendedarticlesview
  15472.  
  15473.     begin tran
  15474.     save TRANSACTION changesubstatus
  15475.  
  15476.         SELECT @finished_virtual = 0
  15477.         SELECT @finished_real = 0
  15478.  
  15479.         /* 
  15480.         ** If @subscriber is null, don't process real subscriptions
  15481.         ** If @subscriber is not null and '%', don't process virtual subscriptions
  15482.         */
  15483.         IF @subscriber IS NULL SELECT @finished_real = 1
  15484.         ELSE IF @subscriber <> '%'  SELECT @finished_virtual = 1
  15485.  
  15486.         WHILE (@finished_real = 0 OR @finished_virtual = 0)
  15487.         BEGIN
  15488.             /*
  15489.             ** Declare cursor containing subscriptions to be updated.
  15490.             */
  15491.             IF @finished_real = 0
  15492.             BEGIN
  15493.                 IF @previous_status IS NOT NULL
  15494.                 BEGIN
  15495.                     DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  15496.                         SELECT sub.artid,
  15497.                                art.objid,
  15498.                                sub.srvid,
  15499.                                ss.srvname,
  15500.                                sub.dest_db,
  15501.                                sub.status,
  15502.                            case when ss.srvproduct = 'MSREPL-NONSQL' or
  15503.                                 pub.allow_dts = 1
  15504.                                 then 1
  15505.                            else 0 end,
  15506.                            pub.repl_freq,
  15507.                                art.type,
  15508.                            pub.immediate_sync,
  15509.                            pub.enabled_for_internet,
  15510.                            pub.allow_anonymous,
  15511.                            sub.subscription_type,
  15512.                            sub.sync_type,
  15513.                            sub.update_mode,
  15514.                            art.name,
  15515.                            sub.login_name,
  15516.                            sub.loopback_detection,
  15517.                            pub.pubid
  15518.                           FROM syssubscriptions sub,
  15519.                                #sysextendedarticlesview art,
  15520.                                syspublications pub,
  15521.                                master..sysservers ss
  15522.                          WHERE pub.name LIKE @publication collate database_default
  15523.                            AND art.name LIKE @article collate database_default
  15524.                            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  15525.                            AND sub.srvid = ss.srvid
  15526.                            AND sub.artid = art.artid
  15527.                            AND art.pubid = pub.pubid
  15528.                            AND sub.status = @prevstatid
  15529.                            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default))
  15530.                 END
  15531.                 ELSE
  15532.                 BEGIN
  15533.                     DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  15534.                         SELECT sub.artid,
  15535.                                art.objid,
  15536.                                sub.srvid,
  15537.                                ss.srvname,
  15538.                                sub.dest_db,
  15539.                                sub.status,
  15540.                            case when ss.srvproduct = 'MSREPL-NONSQL' or
  15541.                                 pub.allow_dts = 1
  15542.                                 then 1
  15543.                            else 0 end,
  15544.                            pub.repl_freq,
  15545.                                art.type,
  15546.                            pub.immediate_sync,
  15547.                            pub.enabled_for_internet,
  15548.                            pub.allow_anonymous,
  15549.                            sub.subscription_type,
  15550.                            sub.sync_type,
  15551.                            sub.update_mode,
  15552.                            art.name,
  15553.                            sub.login_name,
  15554.                            sub.loopback_detection,
  15555.                            pub.pubid
  15556.                           FROM syssubscriptions sub,
  15557.                                #sysextendedarticlesview art,
  15558.                                syspublications pub,
  15559.                                master..sysservers ss
  15560.                          WHERE pub.name LIKE @publication collate database_default
  15561.                            AND art.name LIKE @article collate database_default
  15562.                            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  15563.                            AND sub.srvid = ss.srvid
  15564.                            AND sub.artid = art.artid
  15565.                            AND art.pubid = pub.pubid
  15566.                            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  15567.                 END           
  15568.                 SELECT @finished_real = 1
  15569.             END
  15570.  
  15571.             ELSE IF @finished_virtual = 0  
  15572.             BEGIN
  15573.                 DECLARE @sub_bit smallint
  15574.                 DECLARE @null_name sysname
  15575.  
  15576.                 SELECT @sub_bit = 4
  15577.                 SELECT @null_name = NULL
  15578.  
  15579.                 /*
  15580.                 ** Treat anonymous virtual subscription as DSN subscriber.
  15581.                 ** This will cause sp_MSarticlecol being called in sp_changesubstatus
  15582.                 */
  15583.                 DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  15584.                     SELECT sub.artid,
  15585.                            art.objid,
  15586.                            sub.srvid,
  15587.                            @null_name,              /* subscriber name. NULL for virtual */
  15588.                            sub.dest_db,
  15589.                            sub.status,
  15590.                       case when (pub.allow_anonymous = 1 and (pub.sync_method = @bcp_char or pub.sync_method = @concurrent_char)) or
  15591.                             pub.allow_dts = 1 then 1
  15592.                        else 0 end, /*indicate dsn or not */ 
  15593.                        pub.repl_freq,
  15594.                        art.type,
  15595.                        pub.immediate_sync,
  15596.                        pub.enabled_for_internet,
  15597.                        pub.allow_anonymous,
  15598.                        sub.subscription_type,
  15599.                        sub.sync_type,
  15600.                        sub.update_mode,
  15601.                        art.name,
  15602.                        login_name,
  15603.                        sub.loopback_detection,
  15604.                        pub.pubid
  15605.  
  15606.                       FROM syssubscriptions sub,
  15607.                            #sysextendedarticlesview art,
  15608.                            syspublications pub
  15609.                      WHERE pub.name LIKE @publication
  15610.                        AND art.name LIKE @article
  15611.                        AND sub.srvid = -1
  15612.                        AND sub.artid = art.artid
  15613.                        AND art.pubid = pub.pubid
  15614.                 SELECT @finished_virtual = 1
  15615.             END
  15616.  
  15617.             OPEN hCsubstatus
  15618.             FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db,
  15619.                 @sub_status, @non_sql_flag, @repl_freq, @art_type,
  15620.                 @immediate_sync, @enabled_for_internet,
  15621.                 @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  15622.                 @art_name, @login_name, @loopback_detection,@pubid
  15623.  
  15624.  
  15625.             WHILE (@@fetch_status <> -1)
  15626.             BEGIN
  15627.  
  15628.                 IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  15629.                     AND is_member ('db_owner') <> 1
  15630.                 BEGIN
  15631.                         RAISERROR (14126, 11, -1)
  15632.                         RETURN (1)
  15633.                 END
  15634.                 /*
  15635.                 ** condition 1:
  15636.                 ** If current status is same as new status, and status is not 'initiated' do nothing.
  15637.                 ** If both old and new status = 'initiated', this indicates that the 
  15638.                 ** snapshot agent previously bombed out between the initiation and activation stages and
  15639.                 ** is now again trying to sync the publication.
  15640.                 **
  15641.                 ** condition 2:
  15642.                 ** @auto_sync_only is used by snapshot for immediate_sync
  15643.                 ** publications.
  15644.                 **
  15645.                 ** condition 3:
  15646.                 ** Because sp_MSactivate_auto_sub (and thus the snapshot agent)
  15647.                 ** calls this procedure for all subscriptions, we need to ignore
  15648.                 ** the real subscriptions that are already active so that they won't be
  15649.                 ** transitioned to the initiated state.  If we don't do this, those
  15650.                 ** subscriptions will be resynced using the new snapshot.
  15651.                 ** 
  15652.                 ** however, we DO want a new snapshot to be generated for virtual
  15653.                 ** subscriptions to active publications.
  15654.                 **
  15655.                 */
  15656.                 IF  (@sub_status = @statusid AND @sub_status <> @initiated ) OR
  15657.                     (@from_auto_sync = 1 AND @sync_type <> @automatic) OR
  15658.                     (@sub_status = @active AND @statusid = @initiated AND @srvid <> -1 AND @from_auto_sync = 1)
  15659.                 BEGIN
  15660.                     FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name,
  15661.                        @dest_db, @sub_status, @non_sql_flag, @repl_freq, @art_type, 
  15662.                        @immediate_sync, @enabled_for_internet,
  15663.                        @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  15664.                        @art_name, @login_name, @loopback_detection, @pubid
  15665.  
  15666.                     CONTINUE
  15667.                 END
  15668.  
  15669.                 -- If changing a virtual subscription to 'subscribed' status
  15670.                 -- change the immediate_sync_ready bit
  15671.                 if @statusid = @subscribed and @sub_name is NULL
  15672.                 begin
  15673.                     UPDATE syspublications SET immediate_sync_ready = 0 WHERE 
  15674.                         pubid = @pubid and
  15675.                         immediate_sync_ready <> 0
  15676.                     IF @@ERROR <> 0
  15677.                     BEGIN
  15678.                       CLOSE hCsubstatus
  15679.                       DEALLOCATE hCsubstatus
  15680.                       if @@trancount > 0
  15681.                         begin
  15682.                             ROLLBACK TRANSACTION changesubstatus
  15683.                             commit tran
  15684.                         end
  15685.                       RETURN (1)
  15686.                     END
  15687.                 end
  15688.  
  15689.  
  15690.                 -- acquire schema lock, mark rollback point in order to allow
  15691.                 -- for 'unflush' of proc cache
  15692.  
  15693.                 declare @qualified_name nvarchar(512)
  15694.  
  15695.                 exec dbo.sp_MSget_qualified_name @tabid, @qualified_name output
  15696.                 exec dbo.sp_replupdateschema @qualified_name, @schemastabilityonly
  15697.  
  15698.                 /*
  15699.                 ** Update syssubscription status
  15700.                 */
  15701.                 UPDATE syssubscriptions
  15702.                        SET status = @statusid
  15703.                        FROM syssubscriptions sub,
  15704.                            sysextendedarticlesview art,
  15705.                            syspublications pub
  15706.                        WHERE pub.name LIKE @publication
  15707.                             AND art.artid = @artid
  15708.                             AND sub.srvid = @srvid
  15709.                             AND sub.artid = @artid
  15710.                             AND art.pubid = pub.pubid
  15711.                             AND sub.dest_db = @dest_db
  15712.                 if @@ERROR <> 0
  15713.                                BEGIN
  15714.                                CLOSE hCsubstatus
  15715.                                DEALLOCATE hCsubstatus
  15716.                                 if @@trancount > 0
  15717.                                 begin
  15718.                                     ROLLBACK TRANSACTION changesubstatus
  15719.                                     commit tran
  15720.                                 end
  15721.                                 RAISERROR (14053, 16, -1)
  15722.                                    RETURN (1)
  15723.                                END
  15724.  
  15725.                 --
  15726.                 -- Subscription reinitialization processing for Immediate 
  15727.                 -- and Queued publications
  15728.                 --
  15729.                 if (@update_mode in (1,2,3,4,5))
  15730.                 begin
  15731.                     select @retcode = 0
  15732.                     IF ((@statusid != @active) AND (@sub_status = @active))
  15733.                     begin
  15734.                         --
  15735.                         -- If we are going from active state to subscribed
  15736.                         -- set the reinit column so that no more updates from
  15737.                         -- subscriber are applied until (re)activation
  15738.                         --
  15739.                         update dbo.syssubscriptions
  15740.                         set queued_reinit = 1
  15741.                         where 
  15742.                             artid = @artid 
  15743.                             and srvid = @srvid
  15744.                             and dest_db = @dest_db
  15745.                     end
  15746.                     ELSE IF ((@statusid = @active) AND (@sub_status != @active ))
  15747.                     begin
  15748.                         --
  15749.                         -- If we are going from subscribed state to active state
  15750.                         --
  15751.                         if (@update_mode = 1)
  15752.                         begin
  15753.                             --
  15754.                             -- Sync tran case : reset the reinit column
  15755.                             --
  15756.                             update dbo.syssubscriptions
  15757.                             set queued_reinit = 0
  15758.                             where 
  15759.                                 artid = @artid 
  15760.                                 and srvid = @srvid
  15761.                                 and dest_db = @dest_db
  15762.                         end
  15763.                         --
  15764.                         -- For queued case : we do not need to send compensating
  15765.                         -- command anymore, sp_addqueued_artinfo will do the 
  15766.                         -- queue reinitialization for all types of queued
  15767.                         -- subscriptions
  15768.                         --
  15769.                     end                    
  15770.  
  15771.                     --
  15772.                     -- Check for error
  15773.                     --
  15774.                     if (@@error != 0 or @retcode != 0)
  15775.                     begin
  15776.                         CLOSE hCsubstatus
  15777.                         DEALLOCATE hCsubstatus
  15778.                         if @@trancount > 0
  15779.                         begin
  15780.                             ROLLBACK TRANSACTION changesubstatus
  15781.                             commit tran
  15782.                         end
  15783.                         RAISERROR (14053, 16, -1)
  15784.                         RETURN (1)
  15785.                     end
  15786.                 end
  15787.  
  15788.                 /*
  15789.                 ** Get timestamp of subscription.
  15790.                 */
  15791.                 EXEC @retcode = dbo.sp_replincrementlsn_internal @xact_seqno OUTPUT
  15792.                 IF @@ERROR <> 0 or @retcode <> 0
  15793.                             BEGIN
  15794.                                CLOSE hCsubstatus
  15795.                                DEALLOCATE hCsubstatus
  15796.                                if @@trancount > 0
  15797.                                 begin
  15798.                                     ROLLBACK TRANSACTION changesubstatus
  15799.                                     commit tran
  15800.                                 end
  15801.                                RETURN (1)
  15802.                             END
  15803.                 select @sub_ts = @xact_seqno
  15804.  
  15805.  
  15806.                 IF @sub_ts IS NULL
  15807.                             BEGIN
  15808.                                CLOSE hCsubstatus
  15809.                                DEALLOCATE hCsubstatus
  15810.                                if @@trancount > 0
  15811.                                 begin
  15812.                                     ROLLBACK TRANSACTION changesubstatus
  15813.                                     commit tran
  15814.                                 end
  15815.                                 RAISERROR (14053, 16, -1)
  15816.                                RETURN (1)
  15817.                             END
  15818.                 
  15819.                 -------------------------------------------------------------------
  15820.                 -- If initiating the subscription, toss a SYNCINIT token into the 
  15821.                 -- log for the article and return LSN as a results set
  15822.                 --
  15823.                 -- Note:  This should come after the subscription LSN is obtained.
  15824.                 -- in order to assure proper application of SYNSTAT tokens in the
  15825.                 -- distribution database
  15826.                 -------------------------------------------------------------------
  15827.  
  15828.                 IF @statusid = @initiated --and @sub_status <> @initiated
  15829.                 BEGIN
  15830.                     -- set filtered status.  Must log old text information during initiated state
  15831.                     -- in order to support update splitting
  15832.  
  15833.                     exec sp_MSsetfilteredstatus @tabid
  15834.  
  15835.                     -- set nonsqlsub status.  must prevent UPDATETEXT operations during
  15836.                     -- initiated state
  15837.  
  15838.                     exec sp_MSarticlecol @artid, NULL,N'nonsqlsub', N'add'
  15839.                     exec sp_replpostsyncstatus @pubid, @artid, 1, @syncinit_lsn output
  15840.                     if @f_syncstat_posted = 0
  15841.                     begin
  15842.                         select @pubid, @artid, @syncinit_lsn
  15843.                         select @f_syncstat_posted = 1
  15844.                     end
  15845.                 END
  15846.  
  15847.                 -------------------------------------------------------------------
  15848.                 -- If changing the state FROM initiated, post a SYNCDONE token to the 
  15849.                 -- log for the article. 
  15850.                 -------------------------------------------------------------------
  15851.                 IF @sub_status = @initiated and @statusid <> @initiated
  15852.                 BEGIN
  15853.                     -- reset filtered status to normal value
  15854.  
  15855.                     exec sp_MSsetfilteredstatus @tabid
  15856.  
  15857.                     -- clear nonsqlsub status for this article.
  15858.  
  15859.                     exec sp_MSarticlecol @artid, NULL,N'nonsqlsub', N'drop'
  15860.  
  15861.                     --if @f_syncstat_posted = 0
  15862.                     --begin
  15863.                         exec sp_replpostsyncstatus @pubid, @artid, 0, @syncinit_lsn output
  15864.                     --    select @f_syncstat_posted = 1
  15865.                     --end
  15866.                 END
  15867.  
  15868.                 /*
  15869.                 ** If activating subscription, update sysextendedarticlesview, sysobjects and
  15870.                 ** MSrepl_subscriptions.
  15871.                 */
  15872.                 IF @statusid in ( @active, @initiated )
  15873.                 BEGIN
  15874.                     
  15875.                     /*
  15876.                     ** Update status of article to show it has been activated.
  15877.                     */
  15878.                     IF @repl_freq = 0 and EXISTS (SELECT * FROM sysextendedarticlesview WHERE artid = @artid
  15879.                         AND status & 1 <> 1)
  15880.                     BEGIN
  15881.                         -- At most one row will be updated in the following two updates as the artid is unique
  15882.                         -- among both sysarticles and sysschemaarticles
  15883.                         UPDATE sysarticles SET status = status | 1 WHERE artid = @artid
  15884.                         IF @@ERROR <> 0
  15885.                             BEGIN
  15886.                                 CLOSE hCsubstatus
  15887.                                 DEALLOCATE hCsubstatus
  15888.                                 if @@trancount > 0
  15889.                                 begin
  15890.                                     ROLLBACK TRANSACTION changesubstatus
  15891.                                     commit tran
  15892.                                 end
  15893.                                 RAISERROR (14069, 16, -1)
  15894.                                 RETURN (1)
  15895.                             END
  15896.                         UPDATE sysschemaarticles SET status = status | 1 WHERE artid = @artid
  15897.                         IF @@ERROR <> 0
  15898.                             BEGIN
  15899.                                 CLOSE hCsubstatus
  15900.                                 DEALLOCATE hCsubstatus
  15901.                                 if @@trancount > 0
  15902.                                 begin
  15903.                                     ROLLBACK TRANSACTION changesubstatus
  15904.                                     commit tran
  15905.                                 end
  15906.                                 RAISERROR (14069, 16, -1)
  15907.                                 RETURN (1)
  15908.                             END
  15909.                         SELECT @art_change = 1
  15910.                     END
  15911.  
  15912.                         /*
  15913.                         ** Turn the replication flag on for this object in the
  15914.                         ** sysobjects table (make it logbased).
  15915.                         */
  15916.  
  15917.                     if @repl_freq = 0
  15918.                       BEGIN
  15919.                         UPDATE sysobjects SET replinfo = replinfo | @replicate_bit
  15920.                         WHERE id = ( SELECT objid FROM sysextendedarticlesview WHERE artid = @artid )
  15921.                       END
  15922.  
  15923.                       IF @@ERROR <> 0
  15924.                       BEGIN
  15925.                           CLOSE hCsubstatus
  15926.                           DEALLOCATE hCsubstatus
  15927.                           if @@trancount > 0
  15928.                             begin
  15929.                                 ROLLBACK TRANSACTION changesubstatus
  15930.                                 commit tran
  15931.                             end
  15932.                           RAISERROR (14068, 16, -1)
  15933.                           RETURN (1)
  15934.                       END
  15935.  
  15936.                 END
  15937.  
  15938.                 /*
  15939.                 ** Update status of all columns if subscriber is non-SQL Server.
  15940.                 */
  15941.                 IF @non_sql_flag <> 0 AND ( @art_type & 1 ) = 1
  15942.                 BEGIN
  15943.                     IF @statusid = @subscribed OR @statusid = @active
  15944.                     BEGIN
  15945.  
  15946.                         EXEC @retcode = dbo.sp_MSarticlecol @artid, NULL,
  15947.                                                           'nonsqlsub', 'add'
  15948.                         IF @@ERROR <> 0 OR @retcode <> 0
  15949.                         BEGIN
  15950.                             CLOSE hCsubstatus
  15951.                             DEALLOCATE hCsubstatus
  15952.                             if @@trancount > 0
  15953.                             begin
  15954.                                 ROLLBACK TRANSACTION changesubstatus
  15955.                                 commit tran
  15956.                             end
  15957.                             RAISERROR (14068, 16, -1)
  15958.                             RETURN (1)
  15959.                         END
  15960.  
  15961.  
  15962.                     END
  15963.                     ELSE IF @statusid = @inactive
  15964.                     BEGIN
  15965.  
  15966.                         EXEC @retcode = dbo.sp_MSarticlecol @artid, NULL,
  15967.                                                           'nonsqlsub', 'drop'
  15968.                         IF @@ERROR <> 0 OR @retcode <> 0
  15969.                         BEGIN
  15970.                           CLOSE hCsubstatus
  15971.                           DEALLOCATE hCsubstatus
  15972.                           if @@trancount > 0
  15973.                             begin
  15974.                                 ROLLBACK TRANSACTION changesubstatus
  15975.                                 commit tran
  15976.                             end
  15977.                           RAISERROR (14068, 16, -1)
  15978.                           RETURN (1)
  15979.                         END
  15980.                     END
  15981.                 END
  15982.  
  15983.                 
  15984.                 /*
  15985.                 ** If deactivating subscription, update sysextendedarticlesview, sysobjects and
  15986.                 ** MSrepl_subscriptions.
  15987.                 */
  15988.  
  15989.                 IF @statusid NOT IN( @active, @initiated ) AND @sub_status IN ( @active, @initiated )
  15990.                 BEGIN
  15991.                     /*
  15992.                     ** Set the article status to 'inactive' if there are
  15993.                     ** no other active subscriptions on it.
  15994.                     */
  15995.                     IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  15996.                        artid = @artid AND status = @active)
  15997.                     BEGIN
  15998.                         IF EXISTS (SELECT * FROM sysextendedarticlesview WHERE artid = @artid
  15999.                             AND status & 1 = 1)
  16000.                         BEGIN
  16001.                             -- At most one row will be updated in the following two updates as the artid is unique
  16002.                             -- among both sysarticles and sysschemaarticles
  16003.                             UPDATE sysarticles SET status = status & ~1 WHERE
  16004.                                 artid = @artid
  16005.                             IF @@ERROR <> 0
  16006.                             BEGIN
  16007.                                 CLOSE hCsubstatus
  16008.                                 DEALLOCATE hCsubstatus
  16009.                                 if @@trancount > 0
  16010.                                 begin
  16011.                                     ROLLBACK TRANSACTION changesubstatus
  16012.                                     commit tran
  16013.                                 end
  16014.                                 RAISERROR (14069, 16, -1)
  16015.                                 RETURN (1)
  16016.                             END
  16017.                             UPDATE sysschemaarticles SET status = status & ~1 WHERE
  16018.                                 artid = @artid
  16019.                             IF @@ERROR <> 0
  16020.                             BEGIN
  16021.                                 CLOSE hCsubstatus
  16022.                                 DEALLOCATE hCsubstatus
  16023.                                 if @@trancount > 0
  16024.                                 begin
  16025.                                     ROLLBACK TRANSACTION changesubstatus
  16026.                                     commit tran
  16027.                                 end
  16028.                                 RAISERROR (14069, 16, -1)
  16029.                                 RETURN (1)
  16030.                             END
  16031.  
  16032.                             SELECT @art_change = 1
  16033.                         END
  16034.                     END
  16035.  
  16036.                     /*
  16037.                     ** Set the object replication bits  to 'inactive' if
  16038.                     ** there are no other active subscriptions on the
  16039.                     ** table.
  16040.                     */
  16041.                     IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  16042.                         artid IN (SELECT sa.artid FROM sysextendedarticlesview sa, syspublications sp WHERE
  16043.                         sa.objid = @tabid and sa.pubid = sp.pubid and sp.repl_freq = 0) AND status = @active)
  16044.                     BEGIN
  16045.                         UPDATE sysobjects SET replinfo =  replinfo & ~@replicate_bit
  16046.                         WHERE id = (SELECT objid FROM sysextendedarticlesview WHERE artid = @artid )
  16047.  
  16048.                         IF @@ERROR <> 0
  16049.                         BEGIN
  16050.                            CLOSE hCsubstatus
  16051.                             DEALLOCATE hCsubstatus
  16052.                             RAISERROR (14068, 16, -1)
  16053.                             if @@trancount > 0
  16054.                             begin
  16055.                                 ROLLBACK TRANSACTION changesubstatus
  16056.                                 commit tran
  16057.                             end
  16058.                             RETURN (1)
  16059.                         END
  16060.                     END
  16061.                 END
  16062.  
  16063.                 -- Note:  Not only do we need to have the replupdateschema already executed
  16064.                 -- so we can handle rollbacks, we also need to
  16065.                 -- acquire the schema lock before RPC to the distributor to avoid livelock
  16066.                 -- with snapshot agents. Snapshot agents acquire lock on user table before
  16067.                 -- updating the distribution db.
  16068.  
  16069.                 if @no_distproc = 0
  16070.                 begin
  16071.                     /*
  16072.                     ** Add the active subscription to the distributor's
  16073.                     ** subscriptions table if changing status from @inactive
  16074.                     */
  16075.                     IF @sub_status = @inactive 
  16076.                     -- From inactive to subscribed or active
  16077.                     BEGIN
  16078.  
  16079.                         DECLARE @null_char sysname
  16080.                         SELECT @null_char = NULL
  16081.  
  16082.                         DECLARE @zero_bit bit
  16083.                         SELECT @zero_bit = 0
  16084.  
  16085.                         SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadd_subscription'
  16086.                         EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, 
  16087.                             @artid, @dest_db, @statusid, @sub_ts,
  16088.                             @publication, 
  16089.                             @null_char, /* Pass null to @article, we already gave @artid */
  16090.                             @subscription_type,
  16091.                             --@immediate_sync, 
  16092.                             @sync_type, 
  16093.                             @zero_bit,
  16094.                             @frequency_type,
  16095.                             @frequency_interval,
  16096.                             @frequency_relative_interval,
  16097.                             @frequency_recurrence_factor,
  16098.                             @frequency_subday,
  16099.                             @frequency_subday_interval,
  16100.                             @active_start_time_of_day,
  16101.                             @active_end_time_of_day,
  16102.                             @active_start_date,
  16103.                             @active_end_date,
  16104.                             @optional_command_line = @optional_command_line,
  16105.                             -- synctran
  16106.                             @update_mode = @update_mode,
  16107.                             @loopback_detection = @loopback_detection,
  16108.                             @distribution_jobid = @distribution_jobid OUTPUT,
  16109.                             @offloadagent = @offloadagent,
  16110.                             @offloadserver = @offloadserver,
  16111.                             @dts_package_name = @dts_package_name,
  16112.                             @dts_package_password = @dts_package_password,
  16113.                             @dts_package_location = @dts_package_location,
  16114.                             @distribution_job_name = @distribution_job_name
  16115.  
  16116.                         IF @@ERROR <> 0 OR @retcode <> 0
  16117.                         BEGIN
  16118.                             CLOSE hCsubstatus
  16119.                             DEALLOCATE hCsubstatus
  16120.                             RAISERROR (14070, 16, -1)
  16121.                             if @@trancount > 0
  16122.                             begin
  16123.                                 ROLLBACK TRANSACTION changesubstatus
  16124.                                 commit tran
  16125.                             end
  16126.                             RETURN (1)
  16127.                         END
  16128.                     END
  16129.                     ELSE
  16130.                     -- From subscribed or active to others
  16131.                     BEGIN
  16132.                         /*
  16133.                         ** Drop the deactivated subscription from the distributor's
  16134.                         ** subscriptions table.
  16135.                         */
  16136.                         IF @statusid = @inactive
  16137.                         -- From subscribed to inactive or from active to inactive
  16138.                         BEGIN
  16139.                             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSdrop_subscription'
  16140.                             EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name,  @artid, @dest_db, @publication
  16141.                             IF @@ERROR <> 0 OR @retcode <> 0
  16142.                             BEGIN
  16143.                                 CLOSE hCsubstatus
  16144.                                 DEALLOCATE hCsubstatus
  16145.                                 RAISERROR (14070, 16, -1)
  16146.                                 if @@trancount > 0
  16147.                                 begin
  16148.                                     ROLLBACK TRANSACTION changesubstatus
  16149.                                     commit tran
  16150.                                 end
  16151.                                 RETURN (1)
  16152.                             END
  16153.                         END
  16154.                         ELSE 
  16155.                         -- From subscribed to initiated to active or from active to subscribed.
  16156.                         BEGIN
  16157.                             -- Don't do it if activating the subscription for snapshot agent.
  16158.                             --IF NOT (@from_auto_sync = 1 AND @statusid in(@active, @initiated) )
  16159.                             IF NOT (@from_auto_sync = 1 AND @statusid in(@active) )
  16160.                             BEGIN
  16161.                                 SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSupdate_subscription'
  16162.                                 EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, @artid, @statusid, @sub_ts, @dest_db
  16163.                                 IF @@ERROR <> 0 OR @retcode <> 0
  16164.                                 BEGIN
  16165.                                     CLOSE hCsubstatus
  16166.                                     DEALLOCATE hCsubstatus
  16167.                                     RAISERROR (14070, 16, -1)
  16168.                                     if @@trancount > 0
  16169.                                     begin
  16170.                                         ROLLBACK TRANSACTION changesubstatus
  16171.                                         commit tran
  16172.                                     end
  16173.                                     RETURN (1)
  16174.                                 END
  16175.                             END
  16176.                         END
  16177.                     END
  16178.                 end
  16179.  
  16180.                 /*
  16181.                 ** Set internal object replication bit  to 'inactive' if
  16182.                 ** there are no other active subscriptions on the
  16183.                 ** table.
  16184.                 */
  16185.  
  16186.                 IF @statusid = @inactive AND @sub_status IN (@active,@initiated) AND
  16187.                     NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  16188.                     artid IN (SELECT artid FROM sysextendedarticlesview WHERE
  16189.                     objid = @tabid) AND status IN (@active,@initiated) )
  16190.                 BEGIN
  16191.                        /*
  16192.                        ** If it's a procedure execution article, clear proc status bits
  16193.                        */
  16194.                        IF (@art_type & 8 ) = 8
  16195.                        BEGIN
  16196.                            UPDATE sysobjects SET replinfo = replinfo & ~24 WHERE id = @tabid
  16197.                        END
  16198.                 END
  16199.  
  16200.  
  16201.                 /* Turn on object replication */
  16202.  
  16203.                 ELSE IF @statusid = @active
  16204.                 BEGIN
  16205.                        IF (@art_type & 24 ) = 24
  16206.                        BEGIN
  16207.  
  16208.                            UPDATE sysobjects SET replinfo = replinfo | 24 WHERE id = @tabid
  16209.                        END
  16210.                        ELSE IF( @art_type & 8 ) = 8
  16211.                        BEGIN
  16212.                            UPDATE sysobjects SET replinfo = replinfo | 8 WHERE id = @tabid
  16213.                        END
  16214.                 END
  16215.  
  16216.  
  16217.                 exec dbo.sp_MSget_qualified_name @tabid, @qualified_name output
  16218.                 exec dbo.sp_replupdateschema @qualified_name, @schemastabilityonly
  16219.  
  16220.                /*
  16221.                ** Get next row.
  16222.                */
  16223.                FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db,
  16224.                @sub_status, @non_sql_flag, @repl_freq, @art_type ,  
  16225.                @immediate_sync, @enabled_for_internet,
  16226.                @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  16227.                 @art_name, @login_name, @loopback_detection, @pubid
  16228.  
  16229.           
  16230.                                     
  16231.            END  -- end while for cursor
  16232.  
  16233.            CLOSE hCsubstatus
  16234.            DEALLOCATE hCsubstatus
  16235.         
  16236.         END -- end while for virtual and real
  16237.  
  16238.         -- force refresh of article cache
  16239.         -- Only do it if necessary
  16240.         -- No need on brute force cleanup
  16241.         IF ( @art_change = 1 ) and ( @ignore_distributor = 0 )
  16242.             EXECUTE dbo.sp_replflush
  16243.  
  16244.     COMMIT TRANSACTION
  16245.     drop table #sysextendedarticlesview
  16246.     RETURN(0)
  16247. go
  16248.  
  16249. EXEC dbo.sp_MS_marksystemobject sp_changesubstatus
  16250. GO
  16251. grant execute on dbo.sp_changesubstatus to public
  16252. go
  16253. --------------------------------------------------------------------------------
  16254. --.    System objects (rladmin.sql)
  16255. --------------------------------------------------------------------------------
  16256. --------------------------------------------------------------------------------
  16257. --.    sp_MSremove_userscript
  16258. --------------------------------------------------------------------------------
  16259. if exists (select * from sysobjects
  16260.     where type = 'P' and name = 'sp_MSremove_userscript')
  16261. drop procedure sp_MSremove_userscript
  16262. go
  16263. create procedure sp_MSremove_userscript(
  16264. @pubid                uniqueidentifier,
  16265. @drop_publication    bit = 0
  16266. )as
  16267.     declare @retention            int
  16268.     declare @last_snapshot        datetime
  16269.     declare @post_snapshot_ver    int
  16270.     declare @post_snapshot_type    int
  16271.     declare @user_script_type    int
  16272.     declare @retcode            int
  16273.     declare @len                int
  16274.  
  16275.     declare @file_path            nvarchar(4000)
  16276.     declare @delfile_cmd        nvarchar(4000)
  16277.     declare @rmdir_cmd            nvarchar(4000)
  16278.     
  16279.     select @post_snapshot_type=52
  16280.     select @user_script_type=46
  16281.     
  16282.     if not exists (select * from sysmergeschemachange where pubid=@pubid and schematype=@user_script_type)
  16283.         return (0)
  16284.     select @retention=retention from sysmergepublications where pubid=@pubid
  16285.     select @last_snapshot=last_validated from sysmergesubscriptions where pubid=@pubid and subid=@pubid
  16286.  
  16287.     --I do not want to remove  script files by setting retention to 0
  16288.     if (@retention=0 or dateadd(day, -@retention, getdate()) < @last_snapshot) and @drop_publication = 0
  16289.         return (0)
  16290.  
  16291.     select @post_snapshot_ver=schemaversion from sysmergeschemachange 
  16292.         where schematype=@post_snapshot_type and pubid=@pubid
  16293.         
  16294.     --only get those script that can be safely removed
  16295.     
  16296.     declare #per_script cursor local fast_forward for
  16297.         select schematext from sysmergeschemachange 
  16298.             where pubid=@pubid and schematype=@user_script_type 
  16299.             and (schemaversion<@post_snapshot_ver or @drop_publication = 1)
  16300.     open #per_script
  16301.     fetch #per_script into @file_path
  16302.     while (@@fetch_status<>-1)
  16303.     begin
  16304.     if(left(@file_path, 1) = N'0' or left(@file_path, 1) = N'1')
  16305.         select @file_path = right(@file_path, len(@file_path) - 1)
  16306.         select @delfile_cmd = N'del "' + fn_escapecmdshellsymbolsremovequotes(@file_path) collate database_default + N'"'
  16307.         EXEC @retcode = master..xp_cmdshell @delfile_cmd, NO_OUTPUT
  16308.         if @@ERROR<>0
  16309.             goto FAILURE
  16310.         select @len=CHARINDEX ( '\' , reverse(@file_path) ) 
  16311.         select @file_path=SUBSTRING(@file_path , 1 , len(@file_path)-@len + 1)
  16312.         
  16313.         select @delfile_cmd = N'rmdir "' + fn_escapecmdshellsymbolsremovequotes(@file_path) collate database_default + N'"'
  16314.         EXEC @retcode = master..xp_cmdshell @delfile_cmd, NO_OUTPUT
  16315.         if @@ERROR<>0
  16316.             goto FAILURE
  16317.         fetch next from #per_script into @file_path
  16318.     end
  16319.     
  16320.     close #per_script
  16321.     deallocate #per_script
  16322.     return (0)
  16323. FAILURE:
  16324.     close #per_script
  16325.     deallocate #per_script
  16326.     return (1)
  16327. go
  16328. EXEC dbo.sp_MS_marksystemobject 'sp_MSremove_userscript'
  16329. go
  16330.  
  16331. --------------------------------------------------------------------------------
  16332. --.    sp_MScomputemergearticlescreationorder
  16333. --------------------------------------------------------------------------------
  16334. if exists (select * from sysobjects
  16335.     where type = 'P' and name = 'sp_MScomputemergearticlescreationorder')
  16336. drop procedure sp_MScomputemergearticlescreationorder
  16337. go
  16338. raiserror(15339,-1,-1,'sp_MScomputemergearticlescreationorder')
  16339. GO
  16340. CREATE PROCEDURE sp_MScomputemergearticlescreationorder
  16341.     @publication sysname
  16342. AS
  16343.     SET NOCOUNT ON
  16344.     DECLARE @pubid uniqueidentifier 
  16345.     DECLARE @max_level int
  16346.     DECLARE @current_level int
  16347.     DECLARE @update_level int
  16348.     DECLARE @limit int
  16349.     DECLARE @retcode int
  16350.  
  16351.     SELECT @retcode = 0
  16352.  
  16353.     EXEC @retcode = sp_MSreplcheck_publish
  16354.     IF @@ERROR <> 0 OR @retcode <> 0
  16355.         return (1)
  16356.  
  16357.     SELECT @pubid = NULL
  16358.     -- Get the pubid from sysmergepublications 
  16359.     SELECT @pubid = pubid 
  16360.       FROM sysmergepublications
  16361.      WHERE name = @publication
  16362.        AND UPPER(publisher) = UPPER(@@SERVERNAME)
  16363.        AND publisher_db = DB_NAME()
  16364.  
  16365.     IF @@ERROR <> 0
  16366.         RETURN (1)
  16367.  
  16368.     IF @pubid IS NULL
  16369.     BEGIN
  16370.         RAISERROR(20026, 16, -1, @publication)
  16371.         RETURN (1)
  16372.     END
  16373.  
  16374.     -- Find out the total number of articles in this publication and
  16375.     -- compute the maximum tree height based on the number of articles in 
  16376.     -- the publication. Here, the tree height is counted from the
  16377.     -- leaf-nodes towards the root(s) starting from @max_level
  16378.     SELECT @max_level = COUNT(*) + 10,
  16379.            @limit = 2 * COUNT(*) + 11 
  16380.       FROM sysmergeextendedarticlesview 
  16381.      WHERE pubid = @pubid
  16382.  
  16383.     IF @@ERROR <> 0
  16384.     BEGIN
  16385.         RETURN (1)
  16386.     END
  16387.    
  16388.     -- The following temp table contains the minimal amount of 
  16389.     -- article information that we want to keep around and the current
  16390.     -- computed tree level of the article
  16391.     CREATE TABLE #article_level_info
  16392.     (
  16393.         article         sysname collate database_default not null,
  16394.         source_objid    INT     NOT NULL,
  16395.         tree_level      INT     NOT NULL,
  16396.         nickname        INT     NOT NULL,
  16397.         major_type      TINYINT NOT NULL  -- 1-view&func, 0-other
  16398.     )  
  16399.    
  16400.     CREATE CLUSTERED INDEX ucarticle_level_info 
  16401.         ON #article_level_info(source_objid)
  16402.  
  16403.     IF @@ERROR <> 0
  16404.     BEGIN
  16405.         GOTO Failure
  16406.     END
  16407.  
  16408.     -- Populate the article level info table. All articles will be
  16409.     -- assigned 0 as their initial tree level. Having 
  16410.     -- a tree level of 0 means that the algorithm hasn't discovered 
  16411.     -- any objects that the article depends on within the publication.
  16412.  
  16413.     INSERT INTO #article_level_info 
  16414.     SELECT name, objid, 0, ISNULL(nickname, 5*@max_level),
  16415.         CASE type
  16416.             WHEN 0x40 THEN 1
  16417.             WHEN 0x80 THEN 1
  16418.             ELSE 0
  16419.         END 
  16420.       FROM sysmergeextendedarticlesview
  16421.      WHERE pubid = @pubid
  16422.       
  16423.     -- To jump-start the algorithm, update the tree_level of 
  16424.     -- all articles with no dependency to @max_level.
  16425.  
  16426.     UPDATE #article_level_info 
  16427.        SET tree_level = @max_level
  16428.      WHERE NOT EXISTS (SELECT * 
  16429.                          FROM sysdepends 
  16430.                         WHERE source_objid = id
  16431.                           AND id <> depid)
  16432.     IF @@ERROR <> 0
  16433.         GOTO Failure
  16434.  
  16435.     -- For each increasing tree level starting from @max_level, update the 
  16436.     -- the tree_level of articles depending on objects at the current
  16437.     -- level to current level + 1
  16438.     SELECT @current_level = @max_level
  16439.     WHILE 1 = 1
  16440.     BEGIN
  16441.         SELECT @update_level = @current_level + 1
  16442.  
  16443.         UPDATE #article_level_info
  16444.            SET tree_level = @update_level
  16445.           FROM #article_level_info 
  16446.         INNER JOIN sysdepends d
  16447.             ON #article_level_info.source_objid = d.id 
  16448.         INNER JOIN #article_level_info ali1
  16449.             ON (d.depid = ali1.source_objid       
  16450.                AND ali1.tree_level = @current_level
  16451.                AND d.id <> d.depid)
  16452.     
  16453.         -- Terminate the algorithm if we cannot find any articles 
  16454.         -- depending on articles at the current level     
  16455.         IF @@ROWCOUNT = 0
  16456.             GOTO PHASE1
  16457.  
  16458.         IF @@ERROR <> 0
  16459.             GOTO Failure
  16460.  
  16461.         SELECT @current_level = @current_level + 1
  16462.  
  16463.         -- Although there should not be any circular 
  16464.         -- dependencies among the articles, the following
  16465.         -- check is performed to guarantee that 
  16466.         -- the algorithm will terminate even if there 
  16467.         -- is circular dependency among the articles
  16468.         
  16469.         -- Note that with at least one node per level,
  16470.         -- the current level can never exceed the total 
  16471.         -- number of articles (nodes) unless there is
  16472.         -- circular dependency among the articles.
  16473.         
  16474.         -- @limit is defined to be # of articles + 1
  16475.         -- although @limit = # of articles - 1 will be
  16476.         -- sufficient. This is to make absolutely sure that 
  16477.         -- the algorithm will never terminate too early
  16478.  
  16479.         IF @current_level > @limit
  16480.             GOTO PHASE1
  16481.     END
  16482.  
  16483. PHASE1:
  16484.     
  16485.     -- There may be interdependencies among articles 
  16486.     -- that haven't been included in the previous calculations so
  16487.     -- we compute the proper order among these articles here.
  16488.     SELECT @limit = @max_level - 9
  16489.     SELECT @current_level = 0
  16490.     WHILE 1 = 1
  16491.     BEGIN
  16492.         SELECT @update_level = @current_level + 1
  16493.         
  16494.         UPDATE #article_level_info 
  16495.            SET tree_level = @update_level
  16496.           FROM #article_level_info
  16497.         INNER JOIN sysdepends d
  16498.             ON (#article_level_info.source_objid = d.id
  16499.                 AND #article_level_info.tree_level < @max_level) 
  16500.         INNER JOIN #article_level_info ali1
  16501.             ON (d.depid = ali1.source_objid
  16502.                 AND ali1.tree_level = @current_level
  16503.                 AND d.id <> d.depid)
  16504.         IF @@ROWCOUNT = 0
  16505.             GOTO PHASE2
  16506.         
  16507.         IF @@ERROR <> 0
  16508.             GOTO Failure
  16509.  
  16510.         SELECT @current_level = @current_level + 1
  16511.         IF @current_level > @limit
  16512.             GOTO PHASE2
  16513.     END         
  16514.  
  16515. PHASE2:
  16516.  
  16517.     -- Select the articles out of #article_level_info 
  16518.     -- in ascending order of tree_level. This will give
  16519.     -- the proper order in which articles can be created
  16520.     -- without violating the internal dependencies among
  16521.     -- the themselves. Note that this algorithm still allows 
  16522.     -- unresolved external references outside the publication.
  16523.     -- All this algorithm can guarantee is that all articles will
  16524.     -- be created successfully using the resulting order if 
  16525.     -- there is no dependent object outside the publication. 
  16526.  
  16527.     SELECT article
  16528.       FROM #article_level_info
  16529.     ORDER BY major_type ASC, tree_level ASC, nickname ASC
  16530.  
  16531.     DROP TABLE #article_level_info
  16532.     RETURN (0)
  16533.  
  16534. Failure:
  16535.  
  16536.     DROP TABLE #article_level_info
  16537.     RETURN (1)
  16538. GO
  16539.  
  16540. exec dbo.sp_MS_marksystemobject sp_MScomputemergearticlescreationorder
  16541. go
  16542. grant exec on dbo.sp_MScomputemergearticlescreationorder to public
  16543. go
  16544.  
  16545. --------------------------------------------------------------------------------
  16546. --.    System objects (rlrecon.sql)
  16547. --------------------------------------------------------------------------------
  16548. if exists (select * from sysobjects
  16549.             where type = 'P' and 
  16550.             name = 'sp_MSenumschemachange_80')
  16551.     drop procedure sp_MSenumschemachange_80
  16552.  
  16553. raiserror('Creating procedure sp_MSenumschemachange_80', 0,1)
  16554. GO
  16555.  
  16556. CREATE PROCEDURE sp_MSenumschemachange_80(
  16557.     @pubid                    uniqueidentifier,
  16558.     @AlterTableOnly                    int,
  16559.     @schemaversion            int
  16560.     )
  16561. as
  16562.     set nocount on
  16563.     /*
  16564.     ** To public
  16565.     */
  16566.     declare    @alter_table_type        int
  16567.     declare @reinit_all_type         int
  16568.     declare @reinit_all_upload_type int
  16569.     declare @schemaversion_of_snapshottrailer int
  16570.     
  16571.     select @reinit_all_type = 12
  16572.     select @alter_table_type = 11
  16573.     select @reinit_all_upload_type = 14
  16574.     
  16575.     if (@schemaversion is null)
  16576.         begin
  16577.         RAISERROR(14043, 16, -1, '@schemaversion')
  16578.         return (1)
  16579.         end
  16580.  
  16581.         --    @schema_needed = 0 - only send back reinitall command, if any 
  16582.         --  @schema_needed = 1 - normal enumeration
  16583.         --  @schema_needed = 2 - only send back alter-table command, if any
  16584.         --  @schema_needed = 3 - only send back reinitall-with-upload command, if any.
  16585.  
  16586.     if (@AlterTableOnly = 1)
  16587.         begin
  16588.             select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16589.                 from sysmergeschemachange where pubid=@pubid and schemaversion > @schemaversion and schematype = @alter_table_type
  16590.             return (0)            
  16591.         end
  16592.         
  16593.     if exists (select * from sysmergeschemachange where 
  16594.         pubid=@pubid and ((schemaversion > @schemaversion and schematype = @reinit_all_type)
  16595.         or (schemaversion > @schemaversion and schematype = @reinit_all_upload_type)))
  16596.         begin
  16597.             select @schemaversion=0
  16598.         end
  16599.  
  16600.     -- If subscriber missed a preparecleanup and a completecleanup they must be reinitialized
  16601.     
  16602.     if exists (select * from sysmergeschemachange where 
  16603.         pubid=@pubid and schemaversion > @schemaversion and schematype = 17) and
  16604.         exists (select * from sysmergeschemachange where 
  16605.         pubid=@pubid and schemaversion > @schemaversion and schematype = 19)         
  16606.         begin
  16607.             set @schemaversion=0
  16608.         end
  16609.         
  16610.     if (@schemaversion > 0) 
  16611.     begin
  16612.         -- Subscriber has already received the snapshot so filter out 
  16613.         -- the pre/post-snapshot commands. 
  16614.         -- Also filter out the schemtypes for the setlastsentgen (5) and setlastrecgen (6)
  16615.         -- This ensures that the subscriber does not apply these schema changes when 
  16616.         -- it applies incremental schema - ie the perf optimization that is implemented 
  16617.         -- by setting last sent/rec generation should be done only for brand new subscriptions.
  16618.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16619.           from sysmergeschemachange where schemaversion > @schemaversion  
  16620.            and pubid = @pubid
  16621.            and schematype not in (40, 45, 50, 51, 52, 53, 54, 55, 56, 57, 58, 25, 5, 6)
  16622.       order by schemaversion 
  16623.     end
  16624.     Else 
  16625.     begin
  16626.         -- Subscriber requires a snapshot, so carefully sequence the 
  16627.         -- pre/post-snapshot commands around the snapshot boundary
  16628.  
  16629.         create table #schemachanges 
  16630.         (   
  16631.             pubid           uniqueidentifier  NOT NULL,
  16632.             artid           uniqueidentifier  NULL,
  16633.             schemaversion   int               NOT NULL,
  16634.             schemaguid      uniqueidentifier  NOT NULL,
  16635.             schematype      int               NOT NULL,
  16636.             schematext      nvarchar(2000)    collate database_default not null,
  16637.             seqno           int identity      NOT NULL
  16638.         )
  16639.         
  16640.         truncate table #schemachanges
  16641.         -- Insert snapshot header 
  16642.  
  16643.         -- Header begins
  16644.         insert into #schemachanges
  16645.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16646.           from sysmergeschemachange where schemaversion > @schemaversion 
  16647.            and pubid = @pubid
  16648.            and schematype = 50
  16649.  
  16650.         -- Header content
  16651.         insert into #schemachanges
  16652.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16653.           from sysmergeschemachange where schemaversion > @schemaversion 
  16654.            and pubid = @pubid
  16655.            and schematype in (25, 53, 54, 55, 56, 57, 58) 
  16656.         order by schemaversion 
  16657.  
  16658.         -- Header ends
  16659.         insert into #schemachanges
  16660.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16661.           from sysmergeschemachange where schemaversion > @schemaversion 
  16662.            and pubid = @pubid
  16663.            and schematype = 51 
  16664.  
  16665.         -- End of snapshot header 
  16666.         -- Insert pre command
  16667.         insert into #schemachanges
  16668.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16669.           from sysmergeschemachange where schemaversion > @schemaversion 
  16670.            and pubid = @pubid
  16671.            and schematype = 40 
  16672.  
  16673.         -- Exclude pre-post, but include snapshot only commands
  16674.         insert into #schemachanges
  16675.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16676.           from sysmergeschemachange where schemaversion > @schemaversion 
  16677.            and pubid = @pubid
  16678.            and schematype in (2, 3, 4, 20, 7, 60, 61, 62, 63, 64)
  16679.          order by schemaversion 
  16680.  
  16681.         -- Dynamic BCP commands
  16682.         insert into #schemachanges
  16683.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16684.           from sysmergeschemachange where schemaversion > @schemaversion 
  16685.            and pubid = @pubid
  16686.            and schematype in (131, 132)
  16687.          order by schemaversion         
  16688.         
  16689.         -- DRI/Trg/XPROP
  16690.         insert into #schemachanges
  16691.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16692.           from sysmergeschemachange where schemaversion > @schemaversion 
  16693.            and pubid = @pubid
  16694.            and schematype in (10, 15, 65)
  16695.          order by schemaversion         
  16696.  
  16697.         -- Insert post command
  16698.         insert into #schemachanges
  16699.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16700.           from sysmergeschemachange where schemaversion > @schemaversion 
  16701.            and pubid = @pubid
  16702.            and schematype = 45 
  16703.  
  16704.         -- Insert snapshot trailer
  16705.         insert into #schemachanges
  16706.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16707.           from sysmergeschemachange where schemaversion > @schemaversion 
  16708.            and pubid = @pubid
  16709.            and schematype = 52 
  16710.         
  16711.         -- Insert other schema changes
  16712.         insert into #schemachanges 
  16713.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16714.           from sysmergeschemachange where schemaversion > @schemaversion 
  16715.            and schematype not in (2, 3, 4, 10, 15, 20, 7, 40, 45, 60)
  16716.            and schematype not in (61, 62, 63, 64, 65)
  16717.            and schematype not in (25, 50, 51, 52, 53, 54, 55, 56, 57, 58)
  16718.            and schematype not in (131, 132) -- dynamic bcp commands
  16719.            and schematype not in (46, 11, 13) -- The on-demand script and schema replication commands should not be enumerated unless 
  16720.                                       -- we have made sure that it was posted after the current snapshot.
  16721.            and pubid = @pubid
  16722.          order by schemaversion                   
  16723.  
  16724.         -- get the schemaversion of the snapshot trailer row
  16725.         select @schemaversion_of_snapshottrailer = schemaversion from sysmergeschemachange 
  16726.             where schemaversion > @schemaversion 
  16727.             and pubid = @pubid
  16728.             and schematype = 52 
  16729.  
  16730.         if (@schemaversion_of_snapshottrailer is not null)
  16731.         begin
  16732.             -- insert schema changes for on-demand script and schema replication commands which have schemaversion greater than
  16733.             -- schemaversion of the snapshot trailer row
  16734.             insert into #schemachanges 
  16735.             select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16736.             from sysmergeschemachange where schemaversion > @schemaversion_of_snapshottrailer 
  16737.             and schematype in (46, 11, 13) -- The on-demand script and schema replication commands only.
  16738.             and pubid = @pubid
  16739.             order by schemaversion
  16740.         end
  16741.             
  16742.         declare @endofsnapshot int
  16743.         select @endofsnapshot = min(seqno) from #schemachanges 
  16744.         where schematype = 52
  16745.         delete #schemachanges where seqno > @endofsnapshot
  16746.             and (schematype in (2, 3, 4, 10, 15, 20, 7, 40, 45, 65) or 
  16747.             schematype in (25, 50, 51, 52, 53, 54, 55, 56, 57, 58))
  16748.  
  16749.         --only list the last reinitall command 
  16750.         delete schemachanges1 from #schemachanges schemachanges1,#schemachanges schemachanges2 
  16751.             where schemachanges1.pubid=@pubid and schemachanges1.schematype=12 and 
  16752.                   schemachanges2.pubid=@pubid and schemachanges2.schematype=12 and
  16753.                   schemachanges1.schemaversion<schemachanges2.schemaversion
  16754.         
  16755.         --only list the last reinitall-with-upload command 
  16756.         delete schemachanges1 from #schemachanges schemachanges1, #schemachanges schemachanges2 
  16757.             where schemachanges1.pubid=@pubid and schemachanges1.schematype=14 and 
  16758.                   schemachanges2.pubid=@pubid and schemachanges2.schematype=14 and
  16759.                   schemachanges1.schemaversion<schemachanges2.schemaversion
  16760.  
  16761.         select pubid, artid, schemaversion, schemaguid, schematype, schematext
  16762.           from #schemachanges order by seqno
  16763.  
  16764.         drop table #schemachanges
  16765.     end
  16766.  
  16767.     return (0)
  16768. go
  16769. exec dbo.sp_MS_marksystemobject sp_MSenumschemachange_80
  16770. go
  16771. grant exec on dbo.sp_MSenumschemachange_80 to public
  16772. go
  16773.  
  16774. if exists (select * from sysobjects
  16775.             where type = 'P' and 
  16776.             name = 'sp_MSregistersubscription')
  16777.     drop procedure sp_MSregistersubscription
  16778. go
  16779. raiserror('Creating procedure sp_MSregistersubscription', 0,1)
  16780. go
  16781.  
  16782. CREATE PROCEDURE sp_MSregistersubscription (
  16783.     @replication_type            int, /* Transactional = 1, Merge = 2 */
  16784.     @publisher                     sysname,
  16785.     @publisher_db                 sysname,
  16786.     @publisher_security_mode    int = NULL,                        /* 0 standard; 1 integrated */
  16787.     @publisher_login            sysname = NULL,
  16788.     @publisher_password    nvarchar(524) = NULL,
  16789.     @publication                 sysname,         
  16790.     @subscriber                 sysname,
  16791.     @subscriber_db                 sysname,
  16792.     @subscriber_security_mode    int = NULL,                        /* 0 standard; 1 integrated */
  16793.     @subscriber_login            sysname = NULL,
  16794.     @subscriber_password        nvarchar(524) = NULL,
  16795.     @distributor                 sysname,
  16796.     @distributor_security_mode     int = NULL,
  16797.     @distributor_login             sysname = NULL,
  16798.     @distributor_password        nvarchar(524) = NULL,
  16799.     @subscription_id            uniqueidentifier ,
  16800.     @independent_agent            int = NULL,
  16801.     @subscription_type            int,
  16802.     @use_interactive_resolver    int = NULL,
  16803.     @failover_mode                int = NULL
  16804.     ) AS
  16805.  
  16806.     SET NOCOUNT ON
  16807.  
  16808.     /* MobileSync Support */
  16809.     declare @subscription_name                nvarchar(1000)
  16810.     declare @regkey                            nvarchar(1000)
  16811.     declare @subidstr                        nvarchar(38)
  16812.     declare @profile_name                     nvarchar(100)
  16813.     declare @retcode                        int
  16814.     
  16815.     set @subscription_name = @publisher + ':' + @publisher_db + ':' + @publication + ':' + @subscriber + ':' + @subscriber_db
  16816.     /* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */
  16817.     set @subscription_name = REPLACE(@subscription_name,'\','/')
  16818.     set @regkey = 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\Subscriptions\' + @subscription_name
  16819.     set @subidstr = '{' + convert ( nchar(36), @subscription_id) + '}'
  16820.     set @profile_name = formatmessage(20550) -- SyncMgr Profile
  16821.  
  16822.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16823.                                @regkey,
  16824.                                'ProfileName',
  16825.                                'REG_SZ',
  16826.                                 @profile_name    
  16827.     if @retcode <> 0 OR @@ERROR <> 0
  16828.         return 1
  16829.  
  16830.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16831.                                @regkey,
  16832.                                'ReplicationType',
  16833.                                'REG_DWORD',
  16834.                                 @replication_type    
  16835.     if @retcode <> 0 OR @@ERROR <> 0
  16836.         return 1
  16837.  
  16838.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16839.                                @regkey,
  16840.                                'SubscriptionType',
  16841.                                'REG_DWORD',
  16842.                                 @subscription_type    
  16843.     if @retcode <> 0 OR @@ERROR <> 0
  16844.         return 1
  16845.  
  16846.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16847.                                @regkey,
  16848.                                'Subid',
  16849.                                'REG_SZ',
  16850.                                 @subidstr    
  16851.     if @retcode <> 0 OR @@ERROR <> 0
  16852.         return 1
  16853.  
  16854.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16855.                                @regkey,
  16856.                                'Publisher',
  16857.                                'REG_SZ',
  16858.                                 @publisher                                        
  16859.     if @retcode <> 0 OR @@ERROR <> 0
  16860.         return 1
  16861.  
  16862.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16863.                                @regkey,
  16864.                                'PublisherDb',
  16865.                                'REG_SZ',
  16866.                                 @publisher_db
  16867.     if @retcode <> 0 OR @@ERROR <> 0
  16868.         return 1
  16869.  
  16870.     
  16871.     IF @use_interactive_resolver IS NOT NULL
  16872.     BEGIN
  16873.         EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16874.                                @regkey,
  16875.                                'UseInteractiveResolver',
  16876.                                'REG_DWORD',
  16877.                                 @use_interactive_resolver
  16878.         if @retcode <> 0 OR @@ERROR <> 0
  16879.             return 1
  16880.     END
  16881.  
  16882.     /* If Publisher security mode is NOT NULL, write out the entries */
  16883.     if @publisher_security_mode IS NOT NULL
  16884.         begin
  16885.                EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16886.                                        @regkey,
  16887.                                        'PublisherSecurityMode',
  16888.                                        'REG_DWORD',
  16889.                                         @publisher_security_mode
  16890.             if @retcode <> 0 OR @@ERROR <> 0
  16891.                 return 1
  16892.  
  16893.             EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16894.                                        @regkey,
  16895.                                        'PublisherLogin',
  16896.                                        'REG_SZ',
  16897.                                         @publisher_login                                    
  16898.             if @retcode <> 0 OR @@ERROR <> 0
  16899.                 return 1
  16900.  
  16901.         end
  16902.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16903.                                @regkey,
  16904.                                'Publication',
  16905.                                'REG_SZ',
  16906.                                 @publication
  16907.     if @retcode <> 0 OR @@ERROR <> 0
  16908.         return 1
  16909.  
  16910.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16911.                                @regkey,
  16912.                                'Subscriber',
  16913.                                'REG_SZ',
  16914.                                 @subscriber
  16915.     if @retcode <> 0 OR @@ERROR <> 0
  16916.         return 1
  16917.  
  16918.     /* If Subscriber security mode is NOT NULL, write out the entries */
  16919.     if @subscriber_security_mode IS NOT NULL
  16920.         begin
  16921.             EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16922.                                @regkey,
  16923.                                'SubscriberSecurityMode',
  16924.                                'REG_DWORD',
  16925.                                 @subscriber_security_mode
  16926.             if @retcode <> 0 OR @@ERROR <> 0
  16927.                 return 1
  16928.  
  16929.             EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16930.                                @regkey,
  16931.                                'SubscriberLogin',
  16932.                                'REG_SZ',
  16933.                                 @subscriber_login                                    
  16934.             if @retcode <> 0 OR @@ERROR <> 0
  16935.                 return 1
  16936.  
  16937.         end
  16938.  
  16939.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16940.                                @regkey,
  16941.                                'SubscriberDb',
  16942.                                'REG_SZ',
  16943.                                 @subscriber_db                                    
  16944.     if @retcode <> 0 OR @@ERROR <> 0
  16945.         return 1
  16946.                 
  16947.     EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16948.                                @regkey,
  16949.                                'Distributor',
  16950.                                'REG_SZ',
  16951.                                 @distributor
  16952.     if @retcode <> 0 OR @@ERROR <> 0
  16953.         return 1
  16954.  
  16955.     /* If Distributor security mode is NOT NULL, write out the entries */
  16956.     if @distributor_security_mode IS NOT NULL
  16957.         begin
  16958.             EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16959.                                @regkey,
  16960.                                'DistributorSecurityMode',
  16961.                                'REG_DWORD',
  16962.                                 @distributor_security_mode
  16963.             if @retcode <> 0 OR @@ERROR <> 0
  16964.                 return 1
  16965.  
  16966.             EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16967.                                @regkey,
  16968.                                'DistributorLogin',
  16969.                                'REG_SZ',
  16970.                                 @distributor_login                                    
  16971.             if @retcode <> 0 OR @@ERROR <> 0
  16972.                 return 1
  16973.  
  16974.         end
  16975.  
  16976.     if @independent_agent IS NOT NULL
  16977.         begin
  16978.             EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16979.                                @regkey,
  16980.                                'IndependentAgent',
  16981.                                'REG_DWORD',
  16982.                                 @independent_agent    
  16983.             if @retcode <> 0 OR @@ERROR <> 0
  16984.                 return 1
  16985.         end                
  16986.  
  16987.     IF @failover_mode IS NOT NULL
  16988.         begin
  16989.             EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE',
  16990.                                @regkey,
  16991.                                'FailoverMode',
  16992.                                'REG_DWORD',
  16993.                                 @failover_mode    
  16994.             if @retcode <> 0 OR @@ERROR <> 0
  16995.                 return 1
  16996.  
  16997.         end            
  16998.  
  16999.     -- Mark enabled_for_syncmgr bit if every thing succeeded.
  17000.     -- If the row exists in MSreplication_properties table, 
  17001.     -- set enabled_for_syncmgr bit
  17002.     -- The logic need to be here because UI call this sp directly.
  17003.     if exists (select * from sysobjects where name = 'MSsubscription_properties')
  17004.     begin
  17005.         update MSsubscription_properties set enabled_for_syncmgr = 1 where
  17006.             UPPER(publisher) = UPPER(@publisher)
  17007.             and publisher_db =  @publisher_db
  17008.             and publication = @publication
  17009.         if @retcode <> 0 OR @@ERROR <> 0
  17010.             return 1
  17011.     end
  17012.  
  17013.     return 0
  17014. GO
  17015.  
  17016. exec sp_MS_upd_sysobj_category 2
  17017. go
  17018.  
  17019. exec sp_configure 'allow updates',0
  17020. go
  17021.  
  17022. reconfigure with override
  17023. go
  17024.